r195280 - Fix new check for missing semicolon after struct definition to deal with the
Richard Smith
richard-llvm at metafoo.co.uk
Wed Nov 20 15:40:57 PST 2013
Author: rsmith
Date: Wed Nov 20 17:40:57 2013
New Revision: 195280
URL: http://llvm.org/viewvc/llvm-project?rev=195280&view=rev
Log:
Fix new check for missing semicolon after struct definition to deal with the
case where the type in the following declaration is specified as a template-id,
and refactor for clarity.
Modified:
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/test/Parser/recovery.cpp
cfe/trunk/test/SemaObjCXX/crash.mm
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=195280&r1=195279&r2=195280&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Nov 20 17:40:57 2013
@@ -2338,7 +2338,6 @@ Parser::DiagnoseMissingSemiAfterTagDefin
assert(DS.hasTagDefinition() && "shouldn't call this");
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
- bool HasMissingSemi = false;
if (getLangOpts().CPlusPlus &&
(Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
@@ -2348,58 +2347,71 @@ Parser::DiagnoseMissingSemiAfterTagDefin
return true;
}
+ bool HasScope = Tok.is(tok::annot_cxxscope);
+ // Make a copy in case GetLookAheadToken invalidates the result of NextToken.
+ Token AfterScope = HasScope ? NextToken() : Tok;
+
// Determine whether the following tokens could possibly be a
// declarator.
- if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
- const Token &Next = NextToken();
+ bool MightBeDeclarator = true;
+ if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
+ // A declarator-id can't start with 'typename'.
+ MightBeDeclarator = false;
+ } else if (AfterScope.is(tok::annot_template_id)) {
+ // If we have a type expressed as a template-id, this cannot be a
+ // declarator-id (such a type cannot be redeclared in a simple-declaration).
+ TemplateIdAnnotation *Annot =
+ static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue());
+ if (Annot->Kind == TNK_Type_template)
+ MightBeDeclarator = false;
+ } else if (AfterScope.is(tok::identifier)) {
+ const Token &Next = HasScope ? GetLookAheadToken(2) : NextToken();
+
// These tokens cannot come after the declarator-id in a
// simple-declaration, and are likely to come after a type-specifier.
- HasMissingSemi = Next.is(tok::star) || Next.is(tok::amp) ||
- Next.is(tok::ampamp) || Next.is(tok::identifier) ||
- Next.is(tok::annot_cxxscope) ||
- Next.is(tok::coloncolon);
- } else if (Tok.is(tok::annot_cxxscope) &&
- NextToken().is(tok::identifier) &&
- DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
- // We almost certainly have a missing semicolon. Look up the name and
- // check; if it names a type, we're missing a semicolon.
- CXXScopeSpec SS;
- Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
- Tok.getAnnotationRange(), SS);
- const Token &Next = NextToken();
- IdentifierInfo *Name = Next.getIdentifierInfo();
- Sema::NameClassification Classification =
- Actions.ClassifyName(getCurScope(), SS, Name, Next.getLocation(),
- NextToken(), /*IsAddressOfOperand*/false);
- switch (Classification.getKind()) {
- case Sema::NC_Error:
- SkipMalformedDecl();
- return true;
-
- case Sema::NC_Keyword:
- case Sema::NC_NestedNameSpecifier:
- llvm_unreachable("typo correction and nested name specifiers not "
- "possible here");
-
- case Sema::NC_Type:
- case Sema::NC_TypeTemplate:
- // Not a previously-declared non-type entity.
- HasMissingSemi = true;
- break;
-
- case Sema::NC_Unknown:
- case Sema::NC_Expression:
- case Sema::NC_VarTemplate:
- case Sema::NC_FunctionTemplate:
- // Might be a redeclaration of a prior entity.
- HasMissingSemi = false;
- break;
+ if (Next.is(tok::star) || Next.is(tok::amp) || Next.is(tok::ampamp) ||
+ Next.is(tok::identifier) || Next.is(tok::annot_cxxscope) ||
+ Next.is(tok::coloncolon)) {
+ // Missing a semicolon.
+ MightBeDeclarator = false;
+ } else if (HasScope) {
+ // If the declarator-id has a scope specifier, it must redeclare a
+ // previously-declared entity. If that's a type (and this is not a
+ // typedef), that's an error.
+ CXXScopeSpec SS;
+ Actions.RestoreNestedNameSpecifierAnnotation(
+ Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);
+ IdentifierInfo *Name = AfterScope.getIdentifierInfo();
+ Sema::NameClassification Classification = Actions.ClassifyName(
+ getCurScope(), SS, Name, AfterScope.getLocation(), Next,
+ /*IsAddressOfOperand*/false);
+ switch (Classification.getKind()) {
+ case Sema::NC_Error:
+ SkipMalformedDecl();
+ return true;
+
+ case Sema::NC_Keyword:
+ case Sema::NC_NestedNameSpecifier:
+ llvm_unreachable("typo correction and nested name specifiers not "
+ "possible here");
+
+ case Sema::NC_Type:
+ case Sema::NC_TypeTemplate:
+ // Not a previously-declared non-type entity.
+ MightBeDeclarator = false;
+ break;
+
+ case Sema::NC_Unknown:
+ case Sema::NC_Expression:
+ case Sema::NC_VarTemplate:
+ case Sema::NC_FunctionTemplate:
+ // Might be a redeclaration of a prior entity.
+ break;
+ }
}
- } else if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
- HasMissingSemi = true;
}
- if (!HasMissingSemi)
+ if (MightBeDeclarator)
return false;
Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getLocEnd()),
Modified: cfe/trunk/test/Parser/recovery.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/recovery.cpp?rev=195280&r1=195279&r2=195280&view=diff
==============================================================================
--- cfe/trunk/test/Parser/recovery.cpp (original)
+++ cfe/trunk/test/Parser/recovery.cpp Wed Nov 20 17:40:57 2013
@@ -119,3 +119,13 @@ void MissingSemiInFunction() {
struct Inner4 {} // ok, no missing ';' here
Inner5;
}
+
+namespace NS {
+ template<typename T> struct Foo {};
+}
+struct MissingSemiThenTemplate1 {} // expected-error {{expected ';' after struct}}
+NS::Foo<int> missingSemiBeforeFunctionReturningTemplateId1();
+
+using NS::Foo;
+struct MissingSemiThenTemplate2 {} // expected-error {{expected ';' after struct}}
+Foo<int> missingSemiBeforeFunctionReturningTemplateId2();
Modified: cfe/trunk/test/SemaObjCXX/crash.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/crash.mm?rev=195280&r1=195279&r2=195280&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/crash.mm (original)
+++ cfe/trunk/test/SemaObjCXX/crash.mm Wed Nov 20 17:40:57 2013
@@ -14,10 +14,10 @@ namespace std {
@implementation Test
struct EvilStruct {
-} // note the missing semicolon
+} // expected-error {{expected ';' after struct}}
- typedef std::pair<int, int> IntegerPair; // expected-error{{typedef declarator cannot be qualified}} \
-// expected-error{{typedef name must be an identifier}} \
-// expected-error{{expected ';' after top level declarator}}
+ typedef std::pair<int, int> IntegerPair;
+
+template<typename...Ts> void f(Ts); // expected-error {{unexpanded}} expected-warning {{extension}}
@end
More information about the cfe-commits
mailing list