hokein created this revision.
hokein added a reviewer: sammccall.
Herald added a project: clang.

We mark these decls as invalid.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77037

Files:
  clang/include/clang/AST/DependenceFlags.h
  clang/include/clang/AST/Type.h
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/AST/ast-dump-expr-errors.cpp
  clang/test/Sema/invalid-member.cpp

Index: clang/test/Sema/invalid-member.cpp
===================================================================
--- clang/test/Sema/invalid-member.cpp
+++ clang/test/Sema/invalid-member.cpp
@@ -1,7 +1,15 @@
 // RUN: %clang_cc1 -verify -fsyntax-only %s
-void foo(); // expected-note {{requires 0 arguments}}
+// RUN: %clang_cc1 -verify -fsyntax-only -frecovery-ast %s
+
+void foo(); // expected-note 2{{requires 0 arguments}}
 class X {
   decltype(foo(42)) invalid; // expected-error {{no matching function}}
 };
 // Should be able to evaluate sizeof without crashing.
 static_assert(sizeof(X) == 1, "No valid members");
+
+class Y {
+  typeof(foo(42)) invalid; // expected-error {{no matching function}}
+};
+// Should be able to evaluate sizeof without crashing.
+static_assert(sizeof(Y) == 1, "No valid members");
Index: clang/test/AST/ast-dump-expr-errors.cpp
===================================================================
--- clang/test/AST/ast-dump-expr-errors.cpp
+++ clang/test/AST/ast-dump-expr-errors.cpp
@@ -42,5 +42,9 @@
 
 // FIXME: store initializer even when 'auto' could not be deduced.
 // Expressions with errors currently do not keep initializers around.
-// CHECK:     `-VarDecl {{.*}} invalid e 'auto'
+// CHECK: -VarDecl {{.*}} invalid e 'auto'
 auto e = bar();
+
+// Error type should result in an invalid decl.
+// CHECK: -VarDecl {{.*}} invalid f
+decltype(bar()) f;
\ No newline at end of file
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -1587,7 +1587,7 @@
     assert(E && "Didn't get an expression for typeof?");
     // TypeQuals handled by caller.
     Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
-    if (Result.isNull()) {
+    if (Result.isNull() || Result->isErrorType()) {
       Result = Context.IntTy;
       declarator.setInvalidType(true);
     }
@@ -1598,7 +1598,7 @@
     assert(E && "Didn't get an expression for decltype?");
     // TypeQuals handled by caller.
     Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
-    if (Result.isNull()) {
+    if (Result.isNull() || Result->isErrorType()) {
       Result = Context.IntTy;
       declarator.setInvalidType(true);
     }
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -3105,10 +3105,11 @@
       auto RunSignatureHelp = [&]() {
         ParsedType TypeRep =
             Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
-        assert(TypeRep && "invalid types should be handled before");
-        QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
-            getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
-            DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
+        QualType PreferredType;
+        if (TypeRep)
+          PreferredType = Actions.ProduceConstructorSignatureHelp(
+              getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
+              DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
         CalledSignatureHelp = true;
         return PreferredType;
       };
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -2139,6 +2139,11 @@
     return static_cast<TypeDependence>(TypeBits.Dependence);
   }
 
+  /// Whether this type is an error type.
+  bool isErrorType() const {
+    return getDependence() & TypeDependence::Error;
+  }
+
   /// Whether this type is a dependent type, meaning that its definition
   /// somehow depends on a template parameter (C++ [temp.dep.type]).
   bool isDependentType() const {
Index: clang/include/clang/AST/DependenceFlags.h
===================================================================
--- clang/include/clang/AST/DependenceFlags.h
+++ clang/include/clang/AST/DependenceFlags.h
@@ -50,14 +50,16 @@
     /// Whether this type is a variably-modified type (C99 6.7.5).
     VariablyModified = 8,
 
-    // FIXME: add Error bit.
+    /// Whether this type references an error, e.g. decltype(err-expression)
+    /// yields an error type.
+    Error = 16,
 
     None = 0,
-    All = 15,
+    All = 31,
 
     DependentInstantiation = Dependent | Instantiation,
 
-    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
+    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
   };
 };
 using TypeDependence = TypeDependenceScope::TypeDependence;
@@ -147,6 +149,7 @@
     return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
            translate(V, Instantiation, TypeDependence::Instantiation) |
            translate(V, Dependent, TypeDependence::Dependent) |
+           translate(V, Error, TypeDependence::Error) |
            translate(V, VariablyModified, TypeDependence::VariablyModified);
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to