This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. hokein marked an inline comment as done. Closed by commit rGba6c71b1377e: [AST] Use RecoveryExpr to model a DeclRefExpr which refers to an invalid Decl. (authored by hokein).
Changed prior to commit: https://reviews.llvm.org/D120812?vs=412400&id=412632#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D120812/new/ https://reviews.llvm.org/D120812 Files: clang/lib/Sema/SemaExpr.cpp clang/test/AST/ast-dump-recovery.cpp clang/test/Sema/ms-inline-asm.c clang/test/SemaCXX/constructor-initializer.cpp clang/test/SemaCXX/copy-assignment.cpp Index: clang/test/SemaCXX/copy-assignment.cpp =================================================================== --- clang/test/SemaCXX/copy-assignment.cpp +++ clang/test/SemaCXX/copy-assignment.cpp @@ -114,6 +114,7 @@ namespace test1 { template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}} A(UndeclaredType n) : X(n) {} // expected-error {{unknown type name 'UndeclaredType'}} + // expected-error@-1 {{member initializer 'X' does not name a non-static data member or base class}} }; template<typename T> class B : public A<T> { virtual void foo() {} Index: clang/test/SemaCXX/constructor-initializer.cpp =================================================================== --- clang/test/SemaCXX/constructor-initializer.cpp +++ clang/test/SemaCXX/constructor-initializer.cpp @@ -249,7 +249,9 @@ class B : public A { public: B(const String& s, int e=0) // expected-error {{unknown type name}} - : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}} + : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} \ + expected-error {{member initializer 'm_String' does not name}} \ + expected-error {{member initializer 'm_ErrorStr' does not name}} B(const B& e) : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error 2{{does not name}} \ // expected-error {{no member named 'm_String' in 'test3::B'}} Index: clang/test/Sema/ms-inline-asm.c =================================================================== --- clang/test/Sema/ms-inline-asm.c +++ clang/test/Sema/ms-inline-asm.c @@ -78,7 +78,6 @@ __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}} expected-error {{use of undeclared label 'UndeclaredId'}} // FIXME: Only emit one diagnostic here. - // expected-error@+3 {{use of undeclared label 'A'}} // expected-error@+2 {{unexpected type name 'A': expected expression}} // expected-error@+1 {{unknown token in expression}} __asm { mov eax, [eax] A } Index: clang/test/AST/ast-dump-recovery.cpp =================================================================== --- clang/test/AST/ast-dump-recovery.cpp +++ clang/test/AST/ast-dump-recovery.cpp @@ -401,3 +401,13 @@ // CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 7 // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 8 } + +void RecoveryExprForInvalidDecls(Unknown InvalidDecl) { + InvalidDecl + 1; + // CHECK: BinaryOperator {{.*}} + // CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>' + // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 + InvalidDecl(); + // CHECK: CallExpr {{.*}} + // CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' +} Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -3228,8 +3228,12 @@ "Cannot refer unambiguously to a function template"); SourceLocation Loc = NameInfo.getLoc(); - if (CheckDeclInExpr(*this, Loc, D)) - return ExprError(); + if (CheckDeclInExpr(*this, Loc, D)) { + // Recovery from invalid cases (e.g. D is an invalid Decl). + // We use the dependent type for the RecoveryExpr to prevent bogus follow-up + // diagnostics, as invalid decls use int as a fallback type. + return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); + } if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) { // Specifically diagnose references to class templates that are missing
Index: clang/test/SemaCXX/copy-assignment.cpp =================================================================== --- clang/test/SemaCXX/copy-assignment.cpp +++ clang/test/SemaCXX/copy-assignment.cpp @@ -114,6 +114,7 @@ namespace test1 { template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}} A(UndeclaredType n) : X(n) {} // expected-error {{unknown type name 'UndeclaredType'}} + // expected-error@-1 {{member initializer 'X' does not name a non-static data member or base class}} }; template<typename T> class B : public A<T> { virtual void foo() {} Index: clang/test/SemaCXX/constructor-initializer.cpp =================================================================== --- clang/test/SemaCXX/constructor-initializer.cpp +++ clang/test/SemaCXX/constructor-initializer.cpp @@ -249,7 +249,9 @@ class B : public A { public: B(const String& s, int e=0) // expected-error {{unknown type name}} - : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}} + : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} \ + expected-error {{member initializer 'm_String' does not name}} \ + expected-error {{member initializer 'm_ErrorStr' does not name}} B(const B& e) : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error 2{{does not name}} \ // expected-error {{no member named 'm_String' in 'test3::B'}} Index: clang/test/Sema/ms-inline-asm.c =================================================================== --- clang/test/Sema/ms-inline-asm.c +++ clang/test/Sema/ms-inline-asm.c @@ -78,7 +78,6 @@ __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}} expected-error {{use of undeclared label 'UndeclaredId'}} // FIXME: Only emit one diagnostic here. - // expected-error@+3 {{use of undeclared label 'A'}} // expected-error@+2 {{unexpected type name 'A': expected expression}} // expected-error@+1 {{unknown token in expression}} __asm { mov eax, [eax] A } Index: clang/test/AST/ast-dump-recovery.cpp =================================================================== --- clang/test/AST/ast-dump-recovery.cpp +++ clang/test/AST/ast-dump-recovery.cpp @@ -401,3 +401,13 @@ // CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 7 // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 8 } + +void RecoveryExprForInvalidDecls(Unknown InvalidDecl) { + InvalidDecl + 1; + // CHECK: BinaryOperator {{.*}} + // CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>' + // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 + InvalidDecl(); + // CHECK: CallExpr {{.*}} + // CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' +} Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -3228,8 +3228,12 @@ "Cannot refer unambiguously to a function template"); SourceLocation Loc = NameInfo.getLoc(); - if (CheckDeclInExpr(*this, Loc, D)) - return ExprError(); + if (CheckDeclInExpr(*this, Loc, D)) { + // Recovery from invalid cases (e.g. D is an invalid Decl). + // We use the dependent type for the RecoveryExpr to prevent bogus follow-up + // diagnostics, as invalid decls use int as a fallback type. + return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); + } if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) { // Specifically diagnose references to class templates that are missing
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits