[clang] [clang][ThreadSafety] Enable late parse for all capabilities, under the experimental flag (PR #212615)
Aaron Puchert via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 16:12:13 PDT 2026
================
@@ -701,6 +703,80 @@ 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.
----------------
aaronpuchert wrote:
Sounds like this is related to not treating this as type attribute.
https://github.com/llvm/llvm-project/pull/212615
More information about the cfe-commits
mailing list