summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-07-11 05:10:21 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-07-11 05:10:21 +0000
commit9ce302ed9c29be8f2e9d83f777d20513c3b22109 (patch)
treec58dd33c4b48cf30f53bb3f158a2c2d641214d95
parentc6b5e2499edbbbf588470d91ae21719735aefaa7 (diff)
downloadbcm5719-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.td1
-rw-r--r--clang/include/clang/Sema/DeclSpec.h32
-rw-r--r--clang/lib/Parse/ParseDecl.cpp6
-rw-r--r--clang/test/FixIt/fixit.cpp5
-rw-r--r--clang/test/Parser/cxx-decl.cpp7
-rw-r--r--clang/test/Parser/cxx-template-argument.cpp2
-rw-r--r--clang/test/Parser/cxx0x-decl.cpp7
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}}
+}
OpenPOWER on IntegriCloud