Skip to content

[PATCH 2/4] [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
157 changes: 66 additions & 91 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 @@ -3739,7 +3752,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 @@ -4374,7 +4387,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 @@ -7003,37 +7022,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 @@ -7300,7 +7288,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 @@ -7310,10 +7298,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 @@ -7592,27 +7583,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 @@ -7627,34 +7598,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 Expand Up @@ -7823,7 +7774,7 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifier, specifiesType,
internal::Matcher<QualType>, InnerMatcher) {
if (!Node.getAsType())
if (Node.getKind() != NestedNameSpecifier::Kind::Type)
return false;
return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder);
}
Expand All @@ -7841,8 +7792,12 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
internal::Matcher<TypeLoc>, InnerMatcher) {
return Node && Node.getNestedNameSpecifier()->getAsType() &&
InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder);
if (!Node)
return false;
TypeLoc TL = Node.getAsTypeLoc();
if (!TL)
return false;
return InnerMatcher.matches(TL, Finder, Builder);
}

/// Matches on the prefix of a \c NestedNameSpecifier.
Expand All @@ -7857,10 +7812,21 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
internal::Matcher<NestedNameSpecifier>, InnerMatcher,
0) {
const NestedNameSpecifier *NextNode = Node.getPrefix();
NestedNameSpecifier NextNode = std::nullopt;
switch (Node.getKind()) {
case NestedNameSpecifier::Kind::Namespace:
NextNode = Node.getAsNamespaceAndPrefix().Prefix;
break;
case NestedNameSpecifier::Kind::Type:
NextNode = Node.getAsType()->getPrefix();
break;
default:
break;
}

if (!NextNode)
return false;
return InnerMatcher.matches(*NextNode, Finder, Builder);
return InnerMatcher.matches(NextNode, Finder, Builder);
}

/// Matches on the prefix of a \c NestedNameSpecifierLoc.
Expand All @@ -7875,7 +7841,12 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
internal::Matcher<NestedNameSpecifierLoc>, InnerMatcher,
1) {
NestedNameSpecifierLoc NextNode = Node.getPrefix();
NestedNameSpecifierLoc NextNode;
if (TypeLoc TL = Node.getAsTypeLoc())
NextNode = TL.getPrefix();
else
NextNode = Node.getAsNamespaceAndPrefix().Prefix;

if (!NextNode)
return false;
return InnerMatcher.matches(NextNode, Finder, Builder);
Expand All @@ -7893,9 +7864,13 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
/// matches "ns::"
AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
internal::Matcher<NamespaceDecl>, InnerMatcher) {
if (!Node.getAsNamespace())
if (Node.getKind() != NestedNameSpecifier::Kind::Namespace)
return false;
const auto *Namespace =
dyn_cast<NamespaceDecl>(Node.getAsNamespaceAndPrefix().Namespace);
if (!Namespace)
return false;
return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder);
return InnerMatcher.matches(*Namespace, Finder, Builder);
}

/// Matches attributes.
Expand Down
20 changes: 7 additions & 13 deletions clang/include/clang/ASTMatchers/ASTMatchersInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1013,10 +1013,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 @@ -1027,6 +1024,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 @@ -1062,12 +1062,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 @@ -1207,8 +1201,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 Expand Up @@ -1785,7 +1779,7 @@ class LocMatcher : public MatcherInterface<TLoc> {

private:
static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) {
return DynTypedNode::create(*Loc.getNestedNameSpecifier());
return DynTypedNode::create(Loc.getNestedNameSpecifier());
}
};

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
Loading
Loading