[clang] [clang][ThreadSafety] Enable late parse for all capabilities, under the experimental flag (PR #212615)

Marco Elver via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 25 07:26:36 PDT 2026


================
@@ -715,6 +717,79 @@ void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
   LAs.clear();
 }
 
+/// Collect the references to parameters in \p Attrs' arguments.
+static void collectParamRefs(const ParsedAttributes &Attrs,
+                             SmallVectorImpl<const DeclRefExpr *> &Refs) {
+  SmallVector<const Stmt *, 8> Worklist;
+  for (const ParsedAttr &AL : Attrs)
+    for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I)
+      if (AL.isArgExpr(I))
+        Worklist.push_back(AL.getArgAsExpr(I));
+  while (!Worklist.empty()) {
+    const Stmt *S = Worklist.pop_back_val();
+    if (!S)
+      continue;
+    if (const auto *DRE = dyn_cast<DeclRefExpr>(S);
+        DRE && isa<ParmVarDecl>(DRE->getDecl()))
+      Refs.push_back(DRE);
+    llvm::append_range(Worklist, S->children());
+  }
+}
+
+bool Parser::checkLateAttributeParamRefs(
+    const LateParsedAttribute &LPA, const Decl *D,
+    ArrayRef<const DeclRefExpr *> ParamRefs, bool ReenteredProtoParams) {
+  auto IsPointeeParam = [&](const ParmVarDecl *PVD) {
+    return ReenteredProtoParams && llvm::is_contained(LPA.ProtoParams, PVD);
+  };
+
+  // In a C++ class, attributes were always late parsed and a pointee's
+  // parameters were not in scope, so a name that now binds to one used to bind
+  // to whatever else it names outside the prototype. Rather than silently
+  // change its meaning, reject the attribute as ambiguous.
+  if (getLangOpts().CPlusPlus && getCurScope()->isClassScope()) {
+    for (const DeclRefExpr *DRE : ParamRefs) {
+      const auto *PVD = cast<ParmVarDecl>(DRE->getDecl());
+      if (!IsPointeeParam(PVD))
+        continue;
+      LookupResult R(Actions, PVD->getDeclName(), DRE->getLocation(),
+                     Sema::LookupOrdinaryName);
+      if (!Actions.LookupName(R, getCurScope()) || R.isAmbiguous())
+        continue;
+      Diag(DRE->getLocation(), diag::err_ambiguous_reference)
+          << PVD->getDeclName();
+      Diag(PVD->getLocation(), diag::note_ambiguous_candidate) << PVD;
+      for (const NamedDecl *Other : R)
+        Diag(Other->getLocation(), diag::note_ambiguous_candidate) << Other;
+      return true;
+    }
+  }
+
+  // A name binds the same way in a template, but instantiation cannot yet map a
+  // pointee's parameters, which are instantiated with the declaration's type
+  // and not kept, nor a parameter declared after the one the attribute is on,
+  // which is instantiated after that parameter's attributes. Reject the
+  // attribute rather than instantiate it wrongly.
+  // FIXME: Map these parameters during template instantiation.
+  if (Actions.CurContext->isDependentContext() ||
+      getCurScope()->getTemplateParamParent() ||
+      Actions.getCurGenericLambda()) {
+    const SourceManager &SM = PP.getSourceManager();
+    for (const DeclRefExpr *DRE : ParamRefs) {
+      const auto *PVD = cast<ParmVarDecl>(DRE->getDecl());
----------------
melver wrote:

Checking whether PVD is a later parameter of the same prototype via SM.isBeforeInTranslationUnit can be sensitive to macro expansions and doesn't verify that D and PVD are at the same prototype nesting depth.
  Does this work instead?

```
    -    const SourceManager &SM = PP.getSourceManager();
    +    const auto *DParam = dyn_cast_or_null<ParmVarDecl>(D);
         for (const DeclRefExpr *DRE : ParamRefs) {
           const auto *PVD = cast<ParmVarDecl>(DRE->getDecl());
           bool Pointee = IsPointeeParam(PVD);
           if (!Pointee &&
    -          !(isa<ParmVarDecl>(D) &&
    -            SM.isBeforeInTranslationUnit(D->getLocation(), PVD->getLocation())))
    +          !(DParam &&
    +            DParam->getFunctionScopeDepth() == PVD->getFunctionScopeDepth() &&
    +            DParam->getFunctionScopeIndex() < PVD->getFunctionScopeIndex()))
             continue;
```

https://github.com/llvm/llvm-project/pull/212615


More information about the cfe-commits mailing list