diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-07-11 05:10:21 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-07-11 05:10:21 +0000 |
commit | 9ce302ed9c29be8f2e9d83f777d20513c3b22109 (patch) | |
tree | c58dd33c4b48cf30f53bb3f158a2c2d641214d95 | |
parent | c6b5e2499edbbbf588470d91ae21719735aefaa7 (diff) | |
download | bcm5719-llvm-9ce302ed9c29be8f2e9d83f777d20513c3b22109.tar.gz bcm5719-llvm-9ce302ed9c29be8f2e9d83f777d20513c3b22109.zip |
PR5066: If a declarator cannot have an identifier, and cannot possibly be
followed by an identifier, then diagnose an identifier as being a bogus part of
the declarator instead of tripping over it. Improves diagnostics for cases like
std::vector<const int *p> my_vec;
llvm-svn: 186061
-rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.td | 1 | ||||
-rw-r--r-- | clang/include/clang/Sema/DeclSpec.h | 32 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 6 | ||||
-rw-r--r-- | clang/test/FixIt/fixit.cpp | 5 | ||||
-rw-r--r-- | clang/test/Parser/cxx-decl.cpp | 7 | ||||
-rw-r--r-- | clang/test/Parser/cxx-template-argument.cpp | 2 | ||||
-rw-r--r-- | clang/test/Parser/cxx0x-decl.cpp | 7 |
7 files changed, 59 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 26030775337..d5982e9825d 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -450,6 +450,7 @@ def err_invalid_operator_on_type : Error< "cannot use %select{dot|arrow}0 operator on a type">; def err_expected_unqualified_id : Error< "expected %select{identifier|unqualified-id}0">; +def err_unexpected_unqualified_id : Error<"type-id cannot have a name">; def err_func_def_no_params : Error< "function definition does not declare parameters">; def err_expected_lparen_after_type : Error< diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index ef74abe188b..5924a15b7e4 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1719,6 +1719,38 @@ public: llvm_unreachable("unknown context kind!"); } + /// diagnoseIdentifier - Return true if the identifier is prohibited and + /// should be diagnosed (because it cannot be anything else). + bool diagnoseIdentifier() const { + switch (Context) { + case FileContext: + case KNRTypeListContext: + case MemberContext: + case BlockContext: + case ForContext: + case ConditionContext: + case PrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + case ObjCCatchContext: + case TypeNameContext: + case ConversionIdContext: + case ObjCParameterContext: + case ObjCResultContext: + case BlockLiteralContext: + case CXXNewContext: + case LambdaExprContext: + return false; + + case AliasDeclContext: + case AliasTemplateContext: + case TemplateTypeArgContext: + case TrailingReturnContext: + return true; + } + llvm_unreachable("unknown context kind!"); + } + /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be /// followed by a C++ direct initializer, e.g. "int x(1);". bool mayBeFollowedByCXXDirectInit() const { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7559aa95965..0b276d0b58f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4696,6 +4696,12 @@ void Parser::ParseDirectDeclarator(Declarator &D) { D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); goto PastIdentifier; + } else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) { + Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id) + << FixItHint::CreateRemoval(Tok.getLocation()); + D.SetIdentifier(0, Tok.getLocation()); + ConsumeToken(); + goto PastIdentifier; } if (Tok.is(tok::l_paren)) { diff --git a/clang/test/FixIt/fixit.cpp b/clang/test/FixIt/fixit.cpp index 4e1900a346f..22c1003e8c9 100644 --- a/clang/test/FixIt/fixit.cpp +++ b/clang/test/FixIt/fixit.cpp @@ -307,3 +307,8 @@ namespace dtor_fixit { // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:9}:"foo" }; } + +namespace PR5066 { + template<typename T> struct X {}; + X<int *p> x; // expected-error {{type-id cannot have a name}} +} diff --git a/clang/test/Parser/cxx-decl.cpp b/clang/test/Parser/cxx-decl.cpp index 41d305b1764..e3f3957d564 100644 --- a/clang/test/Parser/cxx-decl.cpp +++ b/clang/test/Parser/cxx-decl.cpp @@ -187,6 +187,13 @@ namespace PR15017 { // Ensure we produce at least some diagnostic for attributes in C++98. [[]] struct S; // expected-error 2{{}} +namespace PR5066 { + template<typename T> struct X {}; + X<int N> x; // expected-error {{type-id cannot have a name}} + + using T = int (*T)(); // expected-error {{type-id cannot have a name}} expected-warning {{C++11}} +} + // PR8380 extern "" // expected-error {{unknown linkage language}} test6a { ;// expected-error {{C++ requires a type specifier for all declarations}} \ diff --git a/clang/test/Parser/cxx-template-argument.cpp b/clang/test/Parser/cxx-template-argument.cpp index afe318df7a1..a2c69be6463 100644 --- a/clang/test/Parser/cxx-template-argument.cpp +++ b/clang/test/Parser/cxx-template-argument.cpp @@ -5,7 +5,7 @@ template<typename T> struct A {}; // Check for template argument lists followed by junk // FIXME: The diagnostics here aren't great... A<int+> int x; // expected-error {{expected '>'}} expected-error {{expected unqualified-id}} -A<int x; // expected-error {{expected '>'}} +A<int x; // expected-error {{type-id cannot have a name}} expected-error {{expected '>'}} // PR8912 template <bool> struct S {}; diff --git a/clang/test/Parser/cxx0x-decl.cpp b/clang/test/Parser/cxx0x-decl.cpp index e6cba726ab6..3d04bfe8160 100644 --- a/clang/test/Parser/cxx0x-decl.cpp +++ b/clang/test/Parser/cxx0x-decl.cpp @@ -73,3 +73,10 @@ enum E [[]] e; } + +namespace PR5066 { + using T = int (*f)(); // expected-error {{type-id cannot have a name}} + template<typename T> using U = int (*f)(); // expected-error {{type-id cannot have a name}} + auto f() -> int (*f)(); // expected-error {{type-id cannot have a name}} + auto g = []() -> int (*f)() {}; // expected-error {{type-id cannot have a name}} +} |