Skip to content

Commit

Permalink
[clang][Index][USR][NFC] Allow customizing langopts for USR generation (
Browse files Browse the repository at this point in the history
#109574)

This helps to produce USRs for custom LangOpts - that differ from the
one associated with the given Decl. This can unlock usecases in tooling
opportunities that we have downstream.

This is NFC because existing calls will still result in the right
overload, thus using the LangOpts associated with the ASTContext of the
Decls and Types.
  • Loading branch information
steakhal authored Oct 30, 2024
1 parent d693e7c commit 4ba623f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 20 deletions.
8 changes: 7 additions & 1 deletion clang/include/clang/Index/USRGeneration.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
namespace clang {
class ASTContext;
class Decl;
class LangOptions;
class MacroDefinitionRecord;
class Module;
class SourceLocation;
Expand All @@ -30,6 +31,8 @@ static inline StringRef getUSRSpacePrefix() {
/// Generate a USR for a Decl, including the USR prefix.
/// \returns true if the results should be ignored, false otherwise.
bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf);
bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf,
const LangOptions &LangOpts);

/// Generate a USR fragment for an Objective-C class.
void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,
Expand Down Expand Up @@ -75,7 +78,10 @@ bool generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
/// Generates a USR for a type.
///
/// \return true on error, false on success.
bool generateUSRForType(QualType T, ASTContext &Ctx, SmallVectorImpl<char> &Buf);
bool generateUSRForType(QualType T, ASTContext &Ctx,
SmallVectorImpl<char> &Buf);
bool generateUSRForType(QualType T, ASTContext &Ctx, SmallVectorImpl<char> &Buf,
const LangOptions &LangOpts);

/// Generate a USR for a module, including the USR prefix.
/// \returns true on error, false on success.
Expand Down
48 changes: 29 additions & 19 deletions clang/lib/Index/USRGeneration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,17 @@ namespace {
class USRGenerator : public ConstDeclVisitor<USRGenerator> {
SmallVectorImpl<char> &Buf;
llvm::raw_svector_ostream Out;
bool IgnoreResults;
ASTContext *Context;
bool generatedLoc;
const LangOptions &LangOpts;
bool IgnoreResults = false;
bool generatedLoc = false;

llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;

public:
explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)
: Buf(Buf),
Out(Buf),
IgnoreResults(false),
Context(Ctx),
generatedLoc(false)
{
USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf,
const LangOptions &LangOpts)
: Buf(Buf), Out(Buf), Context(Ctx), LangOpts(LangOpts) {
// Add the USR space prefix.
Out << getUSRSpacePrefix();
}
Expand Down Expand Up @@ -246,14 +243,13 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
} else
Out << "@F@";

PrintingPolicy Policy(Context->getLangOpts());
PrintingPolicy Policy(LangOpts);
// Forward references can have different template argument names. Suppress the
// template argument names in constructors to make their USR more stable.
Policy.SuppressTemplateArgsInCXXConstructors = true;
D->getDeclName().print(Out, Policy);

ASTContext &Ctx = *Context;
if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) &&
if ((!LangOpts.CPlusPlus || D->isExternC()) &&
!D->hasAttr<OverloadableAttr>())
return;

Expand Down Expand Up @@ -657,9 +653,10 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
return IgnoreResults;
}

static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) {
static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
NestedNameSpecifier *NNS) {
// FIXME: Encode the qualifier, don't just print it.
PrintingPolicy PO(Ctx.getLangOpts());
PrintingPolicy PO(LangOpts);
PO.SuppressTagKeyword = true;
PO.SuppressUnwrittenScope = true;
PO.ConstantArraySizeAsWritten = false;
Expand Down Expand Up @@ -948,7 +945,7 @@ void USRGenerator::VisitType(QualType T) {
}
if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
Out << '^';
printQualifier(Out, Ctx, DNT->getQualifier());
printQualifier(Out, LangOpts, DNT->getQualifier());
Out << ':' << DNT->getIdentifier()->getName();
return;
}
Expand Down Expand Up @@ -1090,7 +1087,7 @@ void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl
return;
VisitDeclContext(D->getDeclContext());
Out << "@UUV@";
printQualifier(Out, D->getASTContext(), D->getQualifier());
printQualifier(Out, LangOpts, D->getQualifier());
EmitDeclName(D);
}

Expand All @@ -1099,7 +1096,7 @@ void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenam
return;
VisitDeclContext(D->getDeclContext());
Out << "@UUT@";
printQualifier(Out, D->getASTContext(), D->getQualifier());
printQualifier(Out, LangOpts, D->getQualifier());
Out << D->getName(); // Simple name.
}

Expand Down Expand Up @@ -1190,6 +1187,13 @@ bool clang::index::generateUSRForDecl(const Decl *D,
SmallVectorImpl<char> &Buf) {
if (!D)
return true;
return generateUSRForDecl(D, Buf, D->getASTContext().getLangOpts());
}

bool clang::index::generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf,
const LangOptions &LangOpts) {
if (!D)
return true;
// We don't ignore decls with invalid source locations. Implicit decls, like
// C++'s operator new function, can have invalid locations but it is fine to
// create USRs that can identify them.
Expand All @@ -1203,7 +1207,7 @@ bool clang::index::generateUSRForDecl(const Decl *D,
return false;
}
}
USRGenerator UG(&D->getASTContext(), Buf);
USRGenerator UG(&D->getASTContext(), Buf, LangOpts);
UG.Visit(D);
return UG.ignoreResults();
}
Expand Down Expand Up @@ -1240,11 +1244,17 @@ bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,

bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
SmallVectorImpl<char> &Buf) {
return generateUSRForType(T, Ctx, Buf, Ctx.getLangOpts());
}

bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
SmallVectorImpl<char> &Buf,
const LangOptions &LangOpts) {
if (T.isNull())
return true;
T = T.getCanonicalType();

USRGenerator UG(&Ctx, Buf);
USRGenerator UG(&Ctx, Buf, LangOpts);
UG.VisitType(T);
return UG.ignoreResults();
}
Expand Down

0 comments on commit 4ba623f

Please sign in to comment.