Please find attached a patch (with testcases) that fixes the source
location info for C++03 access declarations.
While at it, some other improvements in code have been applied, such as:
in a few helper methods of Sema.h:
* renamed isTypeName as HasTypenameKeyword;
in UsingDecl (and UnresolvedUsingValueDecl, if appropriate):
* renamed is/setTypeName as has/setTypename
* renamed get/setUsingLocation to get/setUsingLoc
* added helper isAccessDeclaration()
* fixed getSourceRange
* fixed pretty printing
in UnresolvedUsingTypenameDecl:
* set field UsingLocation in ctor, use it in getUsingLoc
and when (de-)serializing node.
OK to commit?
Enea.
Index: unittests/AST/SourceLocationTest.cpp
===================================================================
--- unittests/AST/SourceLocationTest.cpp (revision 185827)
+++ unittests/AST/SourceLocationTest.cpp (working copy)
@@ -224,5 +224,25 @@
unresolvedConstructExpr(), Args, Lang_CXX11));
}
+TEST(UsingDecl, SourceRange) {
+ RangeVerifier<UsingDecl> Verifier;
+ Verifier.expectRange(2, 22, 2, 25);
+ EXPECT_TRUE(Verifier.match(
+ "class B { protected: int i; };\n"
+ "class D : public B { B::i; };",
+ usingDecl()));
+}
+
+TEST(UnresolvedUsingValueDecl, SourceRange) {
+ RangeVerifier<UnresolvedUsingValueDecl> Verifier;
+ Verifier.expectRange(3, 3, 3, 6);
+ EXPECT_TRUE(Verifier.match(
+ "template <typename B>\n"
+ "class D : public B {\n"
+ " B::i;\n"
+ "};",
+ unresolvedUsingValueDecl()));
+}
+
} // end namespace ast_matchers
} // end namespace clang
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp (revision 185815)
+++ lib/Parse/ParseDeclCXX.cpp (working copy)
@@ -451,7 +451,7 @@
Decl **OwnedType) {
CXXScopeSpec SS;
SourceLocation TypenameLoc;
- bool IsTypeName = false;
+ bool HasTypenameKeyword = false;
ParsedAttributesWithRange Attrs(AttrFactory);
// FIXME: Simply skip the attributes and diagnose, don't bother parsing them.
@@ -464,7 +464,7 @@
// FIXME: This is wrong; we should parse this as a typename-specifier.
if (Tok.is(tok::kw_typename)) {
TypenameLoc = ConsumeToken();
- IsTypeName = true;
+ HasTypenameKeyword = true;
}
// Parse nested-name-specifier.
@@ -549,7 +549,7 @@
// No removal fixit: can't recover from this.
SkipUntil(tok::semi);
return 0;
- } else if (IsTypeName)
+ } else if (HasTypenameKeyword)
Diag(TypenameLoc, diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SourceRange(TypenameLoc,
SS.isNotEmpty() ? SS.getEndLoc() : TypenameLoc));
@@ -593,11 +593,11 @@
// "typename" keyword is allowed for identifiers only,
// because it may be a type definition.
- if (IsTypeName && Name.getKind() != UnqualifiedId::IK_Identifier) {
+ if (HasTypenameKeyword && Name.getKind() != UnqualifiedId::IK_Identifier) {
Diag(Name.getSourceRange().getBegin(), diag::err_typename_identifiers_only)
<< FixItHint::CreateRemoval(SourceRange(TypenameLoc));
- // Proceed parsing, but reset the IsTypeName flag.
- IsTypeName = false;
+ // Proceed parsing, but reset the HasTypenameKeyword flag.
+ HasTypenameKeyword = false;
}
if (IsAliasDecl) {
@@ -610,9 +610,10 @@
TypeAlias);
}
- return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,
- Name, Attrs.getList(),
- IsTypeName, TypenameLoc);
+ return Actions.ActOnUsingDeclaration(getCurScope(), AS,
+ /* HasUsingKeyword */ true, UsingLoc,
+ SS, Name, Attrs.getList(),
+ HasTypenameKeyword, TypenameLoc);
}
/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
@@ -1971,10 +1972,11 @@
return;
Actions.ActOnUsingDeclaration(getCurScope(), AS,
- false, SourceLocation(),
+ /* HasUsingKeyword */ false,
+ SourceLocation(),
SS, Name,
/* AttrList */ 0,
- /* IsTypeName */ false,
+ /* HasTypenameKeyword */ false,
SourceLocation());
return;
}
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp (revision 185815)
+++ lib/Serialization/ASTReaderDecl.cpp (working copy)
@@ -1068,11 +1068,11 @@
void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
- D->setUsingLocation(ReadSourceLocation(Record, Idx));
+ D->setUsingLoc(ReadSourceLocation(Record, Idx));
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>(Record, Idx));
- D->setTypeName(Record[Idx++]);
+ D->setTypename(Record[Idx++]);
if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx))
Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern);
}
@@ -1105,6 +1105,7 @@
void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
+ D->UsingLocation = ReadSourceLocation(Record, Idx);
D->TypenameLocation = ReadSourceLocation(Record, Idx);
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
}
Index: lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- lib/Serialization/ASTWriterDecl.cpp (revision 185815)
+++ lib/Serialization/ASTWriterDecl.cpp (working copy)
@@ -908,11 +908,11 @@
void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
- Writer.AddSourceLocation(D->getUsingLocation(), Record);
+ Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
Writer.AddDeclRef(D->FirstUsingShadow.getPointer(), Record);
- Record.push_back(D->isTypeName());
+ Record.push_back(D->hasTypename());
Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record);
Code = serialization::DECL_USING;
}
@@ -946,6 +946,7 @@
void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
+ Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddSourceLocation(D->getTypenameLoc(), Record);
Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp (revision 185815)
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp (working copy)
@@ -2107,10 +2107,10 @@
Sema::ForRedeclaration);
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
- D->getUsingLocation(),
+ D->getUsingLoc(),
QualifierLoc,
NameInfo,
- D->isTypeName());
+ D->hasTypename());
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
@@ -2119,15 +2119,15 @@
SemaRef.LookupQualifiedName(Prev, Owner);
// Check for invalid redeclarations.
- if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(),
- D->isTypeName(), SS,
+ if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLoc(),
+ D->hasTypename(), SS,
D->getLocation(), Prev))
NewUD->setInvalidDecl();
}
if (!NewUD->isInvalidDecl() &&
- SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS,
D->getLocation()))
NewUD->setInvalidDecl();
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp (revision 185815)
+++ lib/Sema/SemaDeclCXX.cpp (working copy)
@@ -6728,7 +6728,7 @@
CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
@@ -6769,14 +6769,9 @@
if (!TargetName)
return 0;
- // Warn about access declarations.
- // TODO: store that the declaration was written without 'using' and
- // talk about access decls instead of using decls in the
- // diagnostics.
+ // Emit warning (or error) about access declarations.
if (!HasUsingKeyword) {
- UsingLoc = Name.getLocStart();
-
- Diag(UsingLoc,
+ Diag(Name.getLocStart(),
getLangOpts().CPlusPlus11 ? diag::err_access_decl
: diag::warn_access_decl_deprecated)
<< FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
@@ -6789,7 +6784,7 @@
NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
TargetNameInfo, AttrList,
/* IsInstantiation */ false,
- IsTypeName, TypenameLoc);
+ HasTypenameKeyword, TypenameLoc);
if (UD)
PushOnScopeChains(UD, S, /*AddToContext*/ false);
@@ -7035,7 +7030,7 @@
const DeclarationNameInfo &NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
@@ -7070,7 +7065,8 @@
}
// Check for invalid redeclarations.
- if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
+ if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword,
+ SS, IdentLoc, Previous))
return 0;
// Check for bad qualifiers.
@@ -7081,7 +7077,7 @@
NamedDecl *D;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
if (!LookupContext) {
- if (IsTypeName) {
+ if (HasTypenameKeyword) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
UsingLoc, TypenameLoc,
@@ -7093,7 +7089,7 @@
}
} else {
D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
- NameInfo, IsTypeName);
+ NameInfo, HasTypenameKeyword);
}
D->setAccess(AS);
CurContext->addDecl(D);
@@ -7145,7 +7141,7 @@
return UD;
}
- if (IsTypeName) {
+ if (HasTypenameKeyword) {
// If we asked for a typename and got a non-type decl, error out.
if (!R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_typename_non_type);
@@ -7186,7 +7182,7 @@
/// Additional checks for a using declaration referring to a constructor name.
bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
- assert(!UD->isTypeName() && "expecting a constructor name");
+ assert(!UD->hasTypename() && "expecting a constructor name");
const Type *SourceType = UD->getQualifier()->getAsType();
assert(SourceType &&
@@ -7207,7 +7203,7 @@
if (BaseIt == BaseE) {
// Did not find SourceType in the bases.
- Diag(UD->getUsingLocation(),
+ Diag(UD->getUsingLoc(),
diag::err_using_decl_constructor_not_in_direct_base)
<< UD->getNameInfo().getSourceRange()
<< QualType(SourceType, 0) << TargetClass;
@@ -7224,7 +7220,7 @@
/// redeclaration. Note that this is checking only for the using decl
/// itself, not for any ill-formedness among the UsingShadowDecls.
bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
- bool isTypeName,
+ bool HasTypenameKeyword,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Prev) {
@@ -7247,7 +7243,7 @@
bool DTypename;
NestedNameSpecifier *DQual;
if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
- DTypename = UD->isTypeName();
+ DTypename = UD->hasTypename();
DQual = UD->getQualifier();
} else if (UnresolvedUsingValueDecl *UD
= dyn_cast<UnresolvedUsingValueDecl>(D)) {
@@ -7261,7 +7257,7 @@
// using decls differ if one says 'typename' and the other doesn't.
// FIXME: non-dependent using decls?
- if (isTypeName != DTypename) continue;
+ if (HasTypenameKeyword != DTypename) continue;
// using decls differ if they name different scopes (but note that
// template instantiation can cause this check to trigger when it
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h (revision 185815)
+++ lib/Sema/TreeTransform.h (working copy)
@@ -9244,7 +9244,7 @@
TypeDecl *Ty;
if (isa<UsingDecl>(D)) {
UsingDecl *Using = cast<UsingDecl>(D);
- assert(Using->isTypeName() &&
+ assert(Using->hasTypename() &&
"UnresolvedUsingTypenameDecl transformed to non-typename using");
// A valid resolved using typename decl points to exactly one type decl.
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp (revision 185815)
+++ lib/AST/DeclCXX.cpp (working copy)
@@ -1957,8 +1957,8 @@
UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
- bool IsTypeNameArg) {
- return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg);
+ bool HasTypename) {
+ return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename);
}
UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
@@ -1967,6 +1967,12 @@
DeclarationNameInfo(), false);
}
+SourceRange UsingDecl::getSourceRange() const {
+ SourceLocation Begin = isAccessDeclaration()
+ ? getQualifierLoc().getBeginLoc() : UsingLocation;
+ return SourceRange(Begin, getNameInfo().getEndLoc());
+}
+
void UnresolvedUsingValueDecl::anchor() { }
UnresolvedUsingValueDecl *
@@ -1986,6 +1992,12 @@
DeclarationNameInfo());
}
+SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
+ SourceLocation Begin = isAccessDeclaration()
+ ? getQualifierLoc().getBeginLoc() : UsingLocation;
+ return SourceRange(Begin, getNameInfo().getEndLoc());
+}
+
void UnresolvedUsingTypenameDecl::anchor() { }
UnresolvedUsingTypenameDecl *
Index: lib/AST/DeclPrinter.cpp
===================================================================
--- lib/AST/DeclPrinter.cpp (revision 185815)
+++ lib/AST/DeclPrinter.cpp (working copy)
@@ -1155,7 +1155,10 @@
}
void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
- Out << "using ";
+ if (!D->isAccessDeclaration())
+ Out << "using ";
+ if (D->hasTypename())
+ Out << "typename ";
D->getQualifier()->print(Out, Policy);
Out << *D;
}
@@ -1168,7 +1171,8 @@
}
void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
- Out << "using ";
+ if (!D->isAccessDeclaration())
+ Out << "using ";
D->getQualifier()->print(Out, Policy);
Out << D->getName();
}
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h (revision 185815)
+++ include/clang/ASTMatchers/ASTMatchers.h (working copy)
@@ -626,6 +626,21 @@
/// matches \code using X::x \endcode
const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
+/// \brief Matches unresolved using value declarations.
+///
+/// Given
+/// \code
+/// template<typename X>
+/// class C : private X {
+/// using X::x;
+/// };
+/// \endcode
+/// unresolvedUsingValueDecl()
+/// matches \code using X::x \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UnresolvedUsingValueDecl> unresolvedUsingValueDecl;
+
/// \brief Matches constructor call expressions (including implicit ones).
///
/// Example matches string(ptr, n) and ptr within arguments of f
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h (revision 185815)
+++ include/clang/Sema/Sema.h (working copy)
@@ -3553,7 +3553,7 @@
NamedDecl *Target);
bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
- bool isTypeName,
+ bool HasTypenameKeyword,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Previous);
@@ -3567,7 +3567,7 @@
const DeclarationNameInfo &NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc);
bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
@@ -3579,7 +3579,7 @@
CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc);
Decl *ActOnAliasDeclaration(Scope *CurScope,
AccessSpecifier AS,
Index: include/clang/AST/DeclCXX.h
===================================================================
--- include/clang/AST/DeclCXX.h (revision 185815)
+++ include/clang/AST/DeclCXX.h (working copy)
@@ -2705,7 +2705,7 @@
class UsingDecl : public NamedDecl {
virtual void anchor();
- /// \brief The source location of the "using" location itself.
+ /// \brief The source location of the 'using' keyword itself.
SourceLocation UsingLocation;
/// \brief The nested-name-specifier that precedes the name.
@@ -2724,18 +2724,18 @@
UsingDecl(DeclContext *DC, SourceLocation UL,
NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
+ const DeclarationNameInfo &NameInfo, bool HasTypename)
: NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
UsingLocation(UL), QualifierLoc(QualifierLoc),
- DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, IsTypeNameArg) {
+ DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, HasTypename) {
}
public:
- /// \brief Returns the source location of the "using" keyword.
- SourceLocation getUsingLocation() const { return UsingLocation; }
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
- void setUsingLocation(SourceLocation L) { UsingLocation = L; }
+ void setUsingLoc(SourceLocation L) { UsingLocation = L; }
/// \brief Retrieve the nested-name-specifier that qualifies the name,
/// with source-location information.
@@ -2750,11 +2750,14 @@
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
+ /// \brief Return true if it is a C++03 access declaration (no 'using').
+ bool isAccessDeclaration() const { return UsingLocation.isInvalid(); }
+
/// \brief Return true if the using declaration has 'typename'.
- bool isTypeName() const { return FirstUsingShadow.getInt(); }
+ bool hasTypename() const { return FirstUsingShadow.getInt(); }
/// \brief Sets whether the using declaration has 'typename'.
- void setTypeName(bool TN) { FirstUsingShadow.setInt(TN); }
+ void setTypename(bool TN) { FirstUsingShadow.setInt(TN); }
/// \brief Iterates through the using shadow declarations associated with
/// this using declaration.
@@ -2812,14 +2815,12 @@
SourceLocation UsingL,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
- bool IsTypeNameArg);
+ bool HasTypename);
static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(UsingLocation, getNameInfo().getEndLoc());
- }
+ SourceRange getSourceRange() const LLVM_READONLY;
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Using; }
@@ -2868,6 +2869,9 @@
/// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+ /// \brief Return true if it is a C++03 access declaration (no 'using').
+ bool isAccessDeclaration() const { return UsingLocation.isInvalid(); }
+
/// \brief Retrieve the nested-name-specifier that qualifies the name,
/// with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
@@ -2889,9 +2893,7 @@
static UnresolvedUsingValueDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
- SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(UsingLocation, getNameInfo().getEndLoc());
- }
+ SourceRange getSourceRange() const LLVM_READONLY;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
@@ -2930,13 +2932,14 @@
IdentifierInfo *TargetName)
: TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName,
UsingLoc),
- TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { }
+ UsingLocation(UsingLoc), TypenameLocation(TypenameLoc),
+ QualifierLoc(QualifierLoc) { }
friend class ASTDeclReader;
public:
/// \brief Returns the source location of the 'using' keyword.
- SourceLocation getUsingLoc() const { return getLocStart(); }
+ SourceLocation getUsingLoc() const { return UsingLocation; }
/// \brief Returns the source location of the 'typename' keyword.
SourceLocation getTypenameLoc() const { return TypenameLocation; }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits