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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits