[llvm-branch-commits] [cfe-branch] r119245 - in /cfe/branches/Apple/whitney: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h include/clang/Sema/ParsedTemplate.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplate.cpp test/SemaCXX/using-decl-1.cpp test/SemaCXX/using-directive.cpp
Daniel Dunbar
daniel at zuster.org
Mon Nov 15 13:45:47 PST 2010
Author: ddunbar
Date: Mon Nov 15 15:45:47 2010
New Revision: 119245
URL: http://llvm.org/viewvc/llvm-project?rev=119245&view=rev
Log:
Merge r118669:
--
Author: John McCall <rjmccall at apple.com>
Date: Wed Nov 10 02:40:36 2010 +0000
Diagnose attempst to template using declarations and using directives.
Recover from the latter and fail early for the former. Fixes PR8022.
Modified:
cfe/branches/Apple/whitney/include/clang/Basic/DiagnosticParseKinds.td
cfe/branches/Apple/whitney/include/clang/Parse/Parser.h
cfe/branches/Apple/whitney/include/clang/Sema/ParsedTemplate.h
cfe/branches/Apple/whitney/lib/Parse/ParseDecl.cpp
cfe/branches/Apple/whitney/lib/Parse/ParseDeclCXX.cpp
cfe/branches/Apple/whitney/lib/Parse/ParseTemplate.cpp
cfe/branches/Apple/whitney/lib/Sema/SemaDeclCXX.cpp
cfe/branches/Apple/whitney/lib/Sema/SemaTemplate.cpp
cfe/branches/Apple/whitney/test/SemaCXX/using-decl-1.cpp
cfe/branches/Apple/whitney/test/SemaCXX/using-directive.cpp
Modified: cfe/branches/Apple/whitney/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/Basic/DiagnosticParseKinds.td?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/branches/Apple/whitney/include/clang/Basic/DiagnosticParseKinds.td Mon Nov 15 15:45:47 2010
@@ -200,6 +200,10 @@
"unknown type name %0">;
def err_use_of_tag_name_without_tag : Error<
"must use '%1' tag to refer to type %0%select{| in this scope}2">;
+def err_templated_using_directive : Error<
+ "cannot template a using directive">;
+def err_templated_using_declaration : Error<
+ "cannot template a using declaration">;
def err_expected_ident_in_using : Error<
"expected an identifier in using directive">;
def err_unexected_colon_in_nested_name_spec : Error<
Modified: cfe/branches/Apple/whitney/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/Parse/Parser.h?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/Parse/Parser.h (original)
+++ cfe/branches/Apple/whitney/include/clang/Parse/Parser.h Mon Nov 15 15:45:47 2010
@@ -892,6 +892,8 @@
/// \brief Whether the last template parameter list was empty.
bool LastParameterListWasEmpty;
+
+ SourceRange getSourceRange() const;
};
void PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass);
@@ -1508,11 +1510,15 @@
SourceLocation InlineLoc = SourceLocation());
Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd,
CXX0XAttributeList Attrs);
- Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
+ Decl *ParseUsingDirective(unsigned Context,
+ SourceLocation UsingLoc,
SourceLocation &DeclEnd, AttributeList *Attr);
- Decl *ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
+ Decl *ParseUsingDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation UsingLoc,
SourceLocation &DeclEnd,
AccessSpecifier AS = AS_none);
Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
Modified: cfe/branches/Apple/whitney/include/clang/Sema/ParsedTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/Sema/ParsedTemplate.h?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/Sema/ParsedTemplate.h (original)
+++ cfe/branches/Apple/whitney/include/clang/Sema/ParsedTemplate.h Mon Nov 15 15:45:47 2010
@@ -161,7 +161,10 @@
void Destroy() { free(this); }
};
-
+
+ /// Retrieves the range of the given template parameter lists.
+ SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
+ unsigned NumParams);
inline const ParsedTemplateArgument &
ASTTemplateArgsPtr::operator[](unsigned Arg) const {
Modified: cfe/branches/Apple/whitney/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Parse/ParseDecl.cpp?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Parse/ParseDecl.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Parse/ParseDecl.cpp Mon Nov 15 15:45:47 2010
@@ -354,7 +354,8 @@
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)
Modified: cfe/branches/Apple/whitney/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Parse/ParseDeclCXX.cpp?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Parse/ParseDeclCXX.cpp Mon Nov 15 15:45:47 2010
@@ -239,8 +239,9 @@
/// 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 @@
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 @@
/// 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 @@
/// '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 @@
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 @@
} else {
SourceLocation DeclEnd;
// Otherwise, it must be using-declaration.
- ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd, AS);
+ ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
+ UsingLoc, DeclEnd, AS);
}
return;
}
Modified: cfe/branches/Apple/whitney/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Parse/ParseTemplate.cpp?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Parse/ParseTemplate.cpp Mon Nov 15 15:45:47 2010
@@ -196,12 +196,20 @@
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 @@
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;
+}
Modified: cfe/branches/Apple/whitney/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/SemaDeclCXX.cpp?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Sema/SemaDeclCXX.cpp Mon Nov 15 15:45:47 2010
@@ -3402,6 +3402,10 @@
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 @@
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()) {
Modified: cfe/branches/Apple/whitney/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/SemaTemplate.cpp?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Sema/SemaTemplate.cpp Mon Nov 15 15:45:47 2010
@@ -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.
Modified: cfe/branches/Apple/whitney/test/SemaCXX/using-decl-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/SemaCXX/using-decl-1.cpp?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/SemaCXX/using-decl-1.cpp (original)
+++ cfe/branches/Apple/whitney/test/SemaCXX/using-decl-1.cpp Mon Nov 15 15:45:47 2010
@@ -95,3 +95,16 @@
foo(p); // expected-error {{no matching function}}
}
}
+
+namespace test2 {
+ namespace ns { int foo; }
+ template <class T> using ns::foo; // expected-error {{cannot template a using declaration}}
+
+ // PR8022
+ struct A {
+ template <typename T> void f(T);
+ };
+ class B : A {
+ template <typename T> using A::f<T>; // expected-error {{cannot template a using declaration}}
+ };
+}
Modified: cfe/branches/Apple/whitney/test/SemaCXX/using-directive.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/SemaCXX/using-directive.cpp?rev=119245&r1=119244&r2=119245&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/SemaCXX/using-directive.cpp (original)
+++ cfe/branches/Apple/whitney/test/SemaCXX/using-directive.cpp Mon Nov 15 15:45:47 2010
@@ -126,3 +126,10 @@
using namespace std; // expected-warning{{using directive refers to implicitly-defined namespace 'std'}}
using namespace ::std; // expected-warning{{using directive refers to implicitly-defined namespace 'std'}}
+namespace test1 {
+ namespace ns { typedef int test1; }
+ template <class T> using namespace ns; // expected-error {{cannot template a using directive}}
+
+ // Test that we recovered okay.
+ test1 x;
+}
More information about the llvm-branch-commits
mailing list