[clang] ba6c71b - [AST] Use RecoveryExpr to model a DeclRefExpr which refers to an invalid Decl.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 3 01:33:55 PST 2022


Author: Haojian Wu
Date: 2022-03-03T10:33:40+01:00
New Revision: ba6c71b1377e8c99b62b2115a8519df74465f53c

URL: https://github.com/llvm/llvm-project/commit/ba6c71b1377e8c99b62b2115a8519df74465f53c
DIFF: https://github.com/llvm/llvm-project/commit/ba6c71b1377e8c99b62b2115a8519df74465f53c.diff

LOG: [AST] Use RecoveryExpr to model a DeclRefExpr which refers to an invalid Decl.

Previously, we didin't build a DeclRefExpr which refers to an invalid declaration.

In this patch, we handle this case by building an empty RecoveryExpr,
which will preserve more broken code (AST parent nodes that contain the
RecoveryExpr is preserved in the AST).

Differential Revision: https://reviews.llvm.org/D120812

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index bd7110d0315d9..ca5e206f8933d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -3228,8 +3228,12 @@ ExprResult Sema::BuildDeclarationNameExpr(
          "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

diff  --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp
index 0bdd726ab3ce4..f2aca6a78fb02 100644
--- a/clang/test/AST/ast-dump-recovery.cpp
+++ b/clang/test/AST/ast-dump-recovery.cpp
@@ -401,3 +401,13 @@ void returnInitListFromVoid() {
   // 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>'
+}

diff  --git a/clang/test/Sema/ms-inline-asm.c b/clang/test/Sema/ms-inline-asm.c
index 896c74c546d06..fc2a6c294b5c9 100644
--- a/clang/test/Sema/ms-inline-asm.c
+++ b/clang/test/Sema/ms-inline-asm.c
@@ -78,7 +78,6 @@ void t3(void) {
   __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 at +3 {{use of undeclared label 'A'}}
   // expected-error at +2 {{unexpected type name 'A': expected expression}}
   // expected-error at +1 {{unknown token in expression}}
   __asm { mov eax, [eax] A }

diff  --git a/clang/test/SemaCXX/constructor-initializer.cpp b/clang/test/SemaCXX/constructor-initializer.cpp
index 874682944bb85..010f90b59cb07 100644
--- a/clang/test/SemaCXX/constructor-initializer.cpp
+++ b/clang/test/SemaCXX/constructor-initializer.cpp
@@ -249,7 +249,9 @@ namespace test3 {
   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'}}

diff  --git a/clang/test/SemaCXX/copy-assignment.cpp b/clang/test/SemaCXX/copy-assignment.cpp
index d6ad6577895fe..1dbd1037f5b54 100644
--- a/clang/test/SemaCXX/copy-assignment.cpp
+++ b/clang/test/SemaCXX/copy-assignment.cpp
@@ -114,6 +114,7 @@ void test() {
 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 at -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() {}


        


More information about the cfe-commits mailing list