Skip to content
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

[clang][Index][USR][NFC] Allow customizing langopts for USR generation #109574

Merged

Conversation

steakhal
Copy link
Contributor

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.

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.
@steakhal steakhal added the clang Clang issues not falling into any other category label Sep 22, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Sep 22, 2024

@llvm/pr-subscribers-clang

Author: Balazs Benics (steakhal)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/109574.diff

2 Files Affected:

  • (modified) clang/include/clang/Index/USRGeneration.h (+7-1)
  • (modified) clang/lib/Index/USRGeneration.cpp (+29-19)
diff --git a/clang/include/clang/Index/USRGeneration.h b/clang/include/clang/Index/USRGeneration.h
index f89fc5cf49302c..61d267f3545a70 100644
--- a/clang/include/clang/Index/USRGeneration.h
+++ b/clang/include/clang/Index/USRGeneration.h
@@ -15,6 +15,7 @@
 namespace clang {
 class ASTContext;
 class Decl;
+class LangOptions;
 class MacroDefinitionRecord;
 class Module;
 class SourceLocation;
@@ -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,
@@ -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.
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index f00bc56429f1a7..1cfca8b6aaa368 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -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();
   }
@@ -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;
 
@@ -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;
@@ -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;
     }
@@ -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);
 }
 
@@ -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.
 }
 
@@ -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.
@@ -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();
 }
@@ -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();
 }

@steakhal
Copy link
Contributor Author

For example the following code would get different USRs in C and C++:

static int f1(int* x);
// USR in C:   c:input.cc@F@f1
// USR in C++: c:input.cc@F@f1#*I#

So by having this patch, it would be possible to generate the C++ USR even if the AST (thus the ASTContext) was produced for a C compiler invocation.

@steakhal
Copy link
Contributor Author

steakhal commented Oct 1, 2024

ping @sdkrystian

@steakhal
Copy link
Contributor Author

steakhal commented Oct 7, 2024

Ping.

@steakhal
Copy link
Contributor Author

Ping @AaronBallman

@steakhal
Copy link
Contributor Author

@Endilll Could you please help me reaching out to the right set of reviewers?

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Endilll
Copy link
Contributor

Endilll commented Oct 30, 2024

@Endilll Could you please help me reaching out to the right set of reviewers?

Aaron noticed it faster 😄

@steakhal steakhal merged commit 4ba623f into llvm:main Oct 30, 2024
5 of 7 checks passed
@steakhal steakhal deleted the allow-overriding-langopts-for-usr-generation branch October 30, 2024 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants