diff options
author | John McCall <rjmccall@apple.com> | 2010-11-10 02:40:36 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-11-10 02:40:36 +0000 |
commit | 9b72f89f0fade44dc431fdb9557523439f98ae11 (patch) | |
tree | c1c0760cdd280859cddd41d2bdf96d508fc9104c /clang/lib | |
parent | a4ceea8cd86c4fc649c7c79499ae9dddb9ea20e0 (diff) | |
download | bcm5719-llvm-9b72f89f0fade44dc431fdb9557523439f98ae11.tar.gz bcm5719-llvm-9b72f89f0fade44dc431fdb9557523439f98ae11.zip |
Diagnose attempst to template using declarations and using directives.
Recover from the latter and fail early for the former. Fixes PR8022.
llvm-svn: 118669
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 56 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 8 |
5 files changed, 85 insertions, 25 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7e01bacf5cf..2ba47641a03 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -354,7 +354,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, SingleDecl = ParseNamespace(Context, DeclEnd); break; case tok::kw_using: - SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd, Attr); + SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), + DeclEnd, Attr); break; case tok::kw_static_assert: if (Attr.HasAttr) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index a1e67d76997..743442a39c9 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -239,8 +239,9 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or /// using-directive. Assumes that current token is 'using'. Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, - SourceLocation &DeclEnd, - CXX0XAttributeList Attr) { + const ParsedTemplateInfo &TemplateInfo, + SourceLocation &DeclEnd, + CXX0XAttributeList Attr) { assert(Tok.is(tok::kw_using) && "Not using token"); // Eat 'using'. @@ -251,17 +252,26 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, ConsumeCodeCompletionToken(); } - if (Tok.is(tok::kw_namespace)) - // Next token after 'using' is 'namespace' so it must be using-directive + // 'using namespace' means this is a using-directive. + if (Tok.is(tok::kw_namespace)) { + // Template parameters are always an error here. + if (TemplateInfo.Kind) { + SourceRange R = TemplateInfo.getSourceRange(); + Diag(UsingLoc, diag::err_templated_using_directive) + << R << FixItHint::CreateRemoval(R); + } + return ParseUsingDirective(Context, UsingLoc, DeclEnd, Attr.AttrList); + } + // Otherwise, it must be a using-declaration. + + // Using declarations can't have attributes. if (Attr.HasAttr) Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed) << Attr.Range; - // Otherwise, it must be using-declaration. - // Ignore illegal attributes (the caller should already have issued an error. - return ParseUsingDeclaration(Context, UsingLoc, DeclEnd); + return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd); } /// ParseUsingDirective - Parse C++ using-directive, assumes @@ -275,9 +285,9 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, /// namespace-name attributes[opt] ; /// Decl *Parser::ParseUsingDirective(unsigned Context, - SourceLocation UsingLoc, - SourceLocation &DeclEnd, - AttributeList *Attr) { + SourceLocation UsingLoc, + SourceLocation &DeclEnd, + AttributeList *Attr) { assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token"); // Eat 'namespace'. @@ -335,13 +345,18 @@ Decl *Parser::ParseUsingDirective(unsigned Context, /// 'using' :: unqualified-id /// Decl *Parser::ParseUsingDeclaration(unsigned Context, - SourceLocation UsingLoc, - SourceLocation &DeclEnd, - AccessSpecifier AS) { + const ParsedTemplateInfo &TemplateInfo, + SourceLocation UsingLoc, + SourceLocation &DeclEnd, + AccessSpecifier AS) { CXXScopeSpec SS; SourceLocation TypenameLoc; bool IsTypeName; + // TODO: in C++0x, if we have template parameters this must be a + // template alias: + // template <...> using id = type; + // Ignore optional 'typename'. // FIXME: This is wrong; we should parse this as a typename-specifier. if (Tok.is(tok::kw_typename)) { @@ -386,6 +401,18 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, AttrList ? "attributes list" : "using declaration", tok::semi); + // Diagnose an attempt to declare a templated using-declaration. + if (TemplateInfo.Kind) { + SourceRange R = TemplateInfo.getSourceRange(); + Diag(UsingLoc, diag::err_templated_using_declaration) + << R << FixItHint::CreateRemoval(R); + + // Unfortunately, we have to bail out instead of recovering by + // ignoring the parameters, just in case the nested name specifier + // depends on the parameters. + return 0; + } + return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS, Name, AttrList.get(), IsTypeName, TypenameLoc); } @@ -1360,7 +1387,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } else { SourceLocation DeclEnd; // Otherwise, it must be using-declaration. - ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd, AS); + ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo, + UsingLoc, DeclEnd, AS); } return; } diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index c472972e5cb..333d72a754c 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -196,12 +196,20 @@ Parser::ParseSingleDeclarationAfterTemplate( return 0; } + CXX0XAttributeList PrefixAttrs; + if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) + PrefixAttrs = ParseCXX0XAttributes(); + + if (Tok.is(tok::kw_using)) + return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd, + PrefixAttrs); + // Parse the declaration specifiers, stealing the accumulated // diagnostics from the template parameters. ParsingDeclSpec DS(DiagsFromTParams); - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) - DS.AddAttributes(ParseCXX0XAttributes().AttrList); + if (PrefixAttrs.HasAttr) + DS.AddAttributes(PrefixAttrs.AttrList); ParseDeclarationSpecifiers(DS, TemplateInfo, AS, getDeclSpecContextFromDeclaratorContext(Context)); @@ -1075,3 +1083,14 @@ Decl *Parser::ParseExplicitInstantiation(SourceLocation ExternLoc, ParsingTemplateParams, DeclEnd, AS_none); } + +SourceRange Parser::ParsedTemplateInfo::getSourceRange() const { + if (TemplateParams) + return getTemplateParamsRange(TemplateParams->data(), + TemplateParams->size()); + + SourceRange R(TemplateLoc); + if (ExternLoc.isValid()) + R.setBegin(ExternLoc); + return R; +} diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 55dd66f073f..33b31240904 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3402,6 +3402,10 @@ Decl *Sema::ActOnUsingDirective(Scope *S, assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(NamespcName && "Invalid NamespcName."); assert(IdentLoc.isValid() && "Invalid NamespceName location."); + + // This can only happen along a recovery path. + while (S->getFlags() & Scope::TemplateParamScope) + S = S->getParent(); assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); UsingDirectiveDecl *UDir = 0; @@ -3497,14 +3501,14 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { Decl *Sema::ActOnUsingDeclaration(Scope *S, - AccessSpecifier AS, - bool HasUsingKeyword, - SourceLocation UsingLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - AttributeList *AttrList, - bool IsTypeName, - SourceLocation TypenameLoc) { + AccessSpecifier AS, + bool HasUsingKeyword, + SourceLocation UsingLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + AttributeList *AttrList, + bool IsTypeName, + SourceLocation TypenameLoc) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); switch (Name.getKind()) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d7c809f35dd..3243903863d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -30,6 +30,14 @@ using namespace clang; using namespace sema; +// Exported for use by Parser. +SourceRange +clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, + unsigned N) { + if (!N) return SourceRange(); + return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc()); +} + /// \brief Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, /// returns NULL. |