hokein created this revision.
hokein added a reviewer: sammccall.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang.

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).


Repository:
  rG LLVM Github Monorepo

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,7 @@
   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 {{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,7 @@
   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 {{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

Reply via email to