Skip to content

[PATCH 2/6] [clang] Improve nested name specifier AST representation #148012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: users/mizvekov/name-qualification-refactor
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 34 additions & 83 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,19 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl>
typeAliasDecl;

/// \brief Matches shadow declarations introduced into a scope by a
/// (resolved) using declaration.
///
/// Given
/// \code
/// namespace n { int f; }
/// namespace declToImport { using n::f; }
/// \endcode
/// usingShadowDecl()
/// matches \code f \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingShadowDecl>
usingShadowDecl;

/// Matches type alias template declarations.
///
/// typeAliasTemplateDecl() matches
Expand Down Expand Up @@ -3740,7 +3753,7 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> unless;
/// Matcher<MemberExpr>, Matcher<QualType>, Matcher<RecordType>,
/// Matcher<TagType>, Matcher<TemplateSpecializationType>,
/// Matcher<TemplateTypeParmType>, Matcher<TypedefType>,
/// Matcher<UnresolvedUsingType>
/// Matcher<UnresolvedUsingType>, Matcher<UsingType>
inline internal::PolymorphicMatcher<
internal::HasDeclarationMatcher,
void(internal::HasDeclarationSupportedTypes), internal::Matcher<Decl>>
Expand Down Expand Up @@ -4375,7 +4388,13 @@ AST_POLYMORPHIC_MATCHER_P(throughUsingDecl,
AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr,
UsingType),
internal::Matcher<UsingShadowDecl>, Inner) {
const NamedDecl *FoundDecl = Node.getFoundDecl();
const NamedDecl *FoundDecl;
if constexpr (std::is_same_v<NodeType, UsingType>) {
FoundDecl = Node.getDecl();
} else {
static_assert(std::is_same_v<NodeType, DeclRefExpr>);
FoundDecl = Node.getFoundDecl();
}
if (const UsingShadowDecl *UsingDecl = dyn_cast<UsingShadowDecl>(FoundDecl))
return Inner.matches(*UsingDecl, Finder, Builder);
return false;
Expand Down Expand Up @@ -7004,37 +7023,6 @@ AST_POLYMORPHIC_MATCHER_P2(
InnerMatcher.matches(Args[Index], Finder, Builder);
}

/// Matches C or C++ elaborated `TypeLoc`s.
///
/// Given
/// \code
/// struct s {};
/// struct s ss;
/// \endcode
/// elaboratedTypeLoc()
/// matches the `TypeLoc` of the variable declaration of `ss`.
extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, ElaboratedTypeLoc>
elaboratedTypeLoc;

/// Matches elaborated `TypeLoc`s that have a named `TypeLoc` matching
/// `InnerMatcher`.
///
/// Given
/// \code
/// template <typename T>
/// class C {};
/// class C<int> c;
///
/// class D {};
/// class D d;
/// \endcode
/// elaboratedTypeLoc(hasNamedTypeLoc(templateSpecializationTypeLoc()));
/// matches the `TypeLoc` of the variable declaration of `c`, but not `d`.
AST_MATCHER_P(ElaboratedTypeLoc, hasNamedTypeLoc, internal::Matcher<TypeLoc>,
InnerMatcher) {
return InnerMatcher.matches(Node.getNamedTypeLoc(), Finder, Builder);
}

/// Matches type \c bool.
///
/// Given
Expand Down Expand Up @@ -7301,7 +7289,7 @@ extern const AstTypeMatcher<DecltypeType> decltypeType;
AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType));

/// Matches \c DecltypeType or \c UsingType nodes to find the underlying type.
/// Matches \c QualType nodes to find the underlying type.
///
/// Given
/// \code
Expand All @@ -7311,10 +7299,13 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
/// decltypeType(hasUnderlyingType(isInteger()))
/// matches the type of "a"
///
/// Usable as: Matcher<DecltypeType>, Matcher<UsingType>
AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType,
AST_POLYMORPHIC_SUPPORTED_TYPES(DecltypeType,
UsingType));
/// Usable as: Matcher<QualType>
AST_MATCHER_P(Type, hasUnderlyingType, internal::Matcher<QualType>, Inner) {
QualType QT = Node.getLocallyUnqualifiedSingleStepDesugaredType();
if (QT == QualType(&Node, 0))
return false;
return Inner.matches(QT, Finder, Builder);
}

/// Matches \c FunctionType nodes.
///
Expand Down Expand Up @@ -7593,27 +7584,7 @@ extern const AstTypeMatcher<RecordType> recordType;
/// and \c c.
extern const AstTypeMatcher<TagType> tagType;

/// Matches types specified with an elaborated type keyword or with a
/// qualified name.
///
/// Given
/// \code
/// namespace N {
/// namespace M {
/// class D {};
/// }
/// }
/// class C {};
///
/// class C c;
/// N::M::D d;
/// \endcode
///
/// \c elaboratedType() matches the type of the variable declarations of both
/// \c c and \c d.
extern const AstTypeMatcher<ElaboratedType> elaboratedType;

/// Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
/// Matches Types whose qualifier, a NestedNameSpecifier,
/// matches \c InnerMatcher if the qualifier exists.
///
/// Given
Expand All @@ -7628,34 +7599,14 @@ extern const AstTypeMatcher<ElaboratedType> elaboratedType;
///
/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
/// matches the type of the variable declaration of \c d.
AST_MATCHER_P(ElaboratedType, hasQualifier,
internal::Matcher<NestedNameSpecifier>, InnerMatcher) {
if (const NestedNameSpecifier *Qualifier = Node.getQualifier())
return InnerMatcher.matches(*Qualifier, Finder, Builder);
AST_MATCHER_P(Type, hasQualifier, internal::Matcher<NestedNameSpecifier>,
InnerMatcher) {
if (NestedNameSpecifier Qualifier = Node.getPrefix())
return InnerMatcher.matches(Qualifier, Finder, Builder);

return false;
}

/// Matches ElaboratedTypes whose named type matches \c InnerMatcher.
///
/// Given
/// \code
/// namespace N {
/// namespace M {
/// class D {};
/// }
/// }
/// N::M::D d;
/// \endcode
///
/// \c elaboratedType(namesType(recordType(
/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
/// declaration of \c d.
AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
InnerMatcher) {
return InnerMatcher.matches(Node.getNamedType(), Finder, Builder);
}

/// Matches types specified through a using declaration.
///
/// Given
Expand Down
18 changes: 6 additions & 12 deletions clang/include/clang/ASTMatchers/ASTMatchersInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1017,10 +1017,7 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
// First, for any types that have a declaration, extract the declaration and
// match on it.
if (const auto *S = dyn_cast<TagType>(&Node)) {
return matchesDecl(S->getDecl(), Finder, Builder);
}
if (const auto *S = dyn_cast<InjectedClassNameType>(&Node)) {
return matchesDecl(S->getDecl(), Finder, Builder);
return matchesDecl(S->getOriginalDecl(), Finder, Builder);
}
if (const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) {
return matchesDecl(S->getDecl(), Finder, Builder);
Expand All @@ -1031,6 +1028,9 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
if (const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) {
return matchesDecl(S->getDecl(), Finder, Builder);
}
if (const auto *S = dyn_cast<UsingType>(&Node)) {
return matchesDecl(S->getDecl(), Finder, Builder);
}
if (const auto *S = dyn_cast<ObjCObjectType>(&Node)) {
return matchesDecl(S->getInterface(), Finder, Builder);
}
Expand Down Expand Up @@ -1066,12 +1066,6 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
Builder);
}

// FIXME: We desugar elaborated types. This makes the assumption that users
// do never want to match on whether a type is elaborated - there are
// arguments for both sides; for now, continue desugaring.
if (const auto *S = dyn_cast<ElaboratedType>(&Node)) {
return matchesSpecialized(S->desugar(), Finder, Builder);
}
// Similarly types found via using declarations.
// These are *usually* meaningless sugar, and this matches the historical
// behavior prior to the introduction of UsingType.
Expand Down Expand Up @@ -1211,8 +1205,8 @@ using AdaptativeDefaultToTypes =
/// All types that are supported by HasDeclarationMatcher above.
using HasDeclarationSupportedTypes =
TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
MemberExpr, QualType, RecordType, TagType,
InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr,
QualType, RecordType, TagType, UsingType,
TemplateSpecializationType, TemplateTypeParmType, TypedefType,
UnresolvedUsingType, ObjCIvarRefExpr, ObjCInterfaceDecl>;

Expand Down
10 changes: 8 additions & 2 deletions clang/include/clang/Analysis/FlowSensitive/ASTOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,14 @@ class AnalysisASTVisitor : public DynamicRecursiveASTVisitor {
// fields that are only used in these.
// Note: The operand of the `noexcept` operator is an unevaluated operand, but
// nevertheless it appears in the Clang CFG, so we don't exclude it here.
bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) override { return true; }
bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) override { return true; }
bool TraverseDecltypeTypeLoc(DecltypeTypeLoc,
bool TraverseQualifier) override {
return true;
}
bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc,
bool TraverseQualifier) override {
return true;
}
bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) override {
if (TIE->isPotentiallyEvaluated())
return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(TIE);
Expand Down
24 changes: 5 additions & 19 deletions clang/include/clang/Sema/DeclSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,21 +106,7 @@ class CXXScopeSpec {
/// \param TL The TypeLoc that describes the type preceding the '::'.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc);

/// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'identifier::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param Identifier The identifier.
///
/// \param IdentifierLoc The location of the identifier.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, IdentifierInfo *Identifier,
SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
void Make(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc);

/// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace::'.
Expand Down Expand Up @@ -189,14 +175,14 @@ class CXXScopeSpec {
SourceLocation getLastQualifierNameLoc() const;

/// No scope specifier.
bool isEmpty() const { return Range.isInvalid() && getScopeRep() == nullptr; }
bool isEmpty() const { return Range.isInvalid() && !getScopeRep(); }
/// A scope specifier is present, but may be valid or invalid.
bool isNotEmpty() const { return !isEmpty(); }

/// An error occurred during parsing of the scope specifier.
bool isInvalid() const { return Range.isValid() && getScopeRep() == nullptr; }
bool isInvalid() const { return Range.isValid() && !getScopeRep(); }
/// A scope specifier is present, and it refers to a real scope.
bool isValid() const { return getScopeRep() != nullptr; }
bool isValid() const { return bool(getScopeRep()); }

/// Indicate that this nested-name-specifier is invalid.
void SetInvalid(SourceRange R) {
Expand All @@ -209,7 +195,7 @@ class CXXScopeSpec {

/// Deprecated. Some call sites intend isNotEmpty() while others intend
/// isValid().
bool isSet() const { return getScopeRep() != nullptr; }
bool isSet() const { return bool(getScopeRep()); }

void clear() {
Range = SourceRange();
Expand Down
26 changes: 16 additions & 10 deletions clang/include/clang/Sema/ParsedTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ namespace clang {
///
/// \param Arg the template type argument or non-type template argument.
/// \param Loc the location of the type.
ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
: Kind(Kind), Arg(Arg), Loc(Loc) { }
ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation NameLoc)
: Kind(Kind), Arg(Arg), NameLoc(NameLoc) {}

/// Create a template template argument.
///
Expand All @@ -60,11 +60,11 @@ namespace clang {
/// argument refers.
///
/// \param TemplateLoc the location of the template name.
ParsedTemplateArgument(const CXXScopeSpec &SS,
ParsedTemplateTy Template,
SourceLocation TemplateLoc)
: Kind(ParsedTemplateArgument::Template),
Arg(Template.getAsOpaquePtr()), SS(SS), Loc(TemplateLoc) {}
ParsedTemplateArgument(SourceLocation TemplateKwLoc, const CXXScopeSpec &SS,
ParsedTemplateTy Template, SourceLocation NameLoc)
: Kind(ParsedTemplateArgument::Template),
Arg(Template.getAsOpaquePtr()), SS(SS), TemplateKwLoc(TemplateKwLoc),
NameLoc(NameLoc) {}

/// Determine whether the given template argument is invalid.
bool isInvalid() const { return Arg == nullptr; }
Expand All @@ -91,7 +91,10 @@ namespace clang {
}

/// Retrieve the location of the template argument.
SourceLocation getLocation() const { return Loc; }
SourceLocation getTemplateKwLoc() const { return TemplateKwLoc; }

/// Retrieve the location of the template argument.
SourceLocation getNameLoc() const { return NameLoc; }

/// Retrieve the nested-name-specifier that precedes the template
/// name in a template template argument.
Expand Down Expand Up @@ -128,8 +131,11 @@ namespace clang {
/// argument.
CXXScopeSpec SS;

/// the location of the template argument.
SourceLocation Loc;
/// the location of the template keyword.
SourceLocation TemplateKwLoc;

/// the location of the template name.
SourceLocation NameLoc;

/// The ellipsis location that can accompany a template template
/// argument (turning it into a template template argument expansion).
Expand Down
Loading
Loading