[clang] "modular_format" attribute for functions using format strings
This provides a C language version of the new IR modular-format attribute. This, in concert with the format attribute, allows a library function to declare that a modular version of its implementation is available. See issue #146159 for context.
This commit is contained in:
parent
9265309f0c
commit
4c53b27ac2
@ -5233,3 +5233,14 @@ def NonString : InheritableAttr {
|
||||
let Subjects = SubjectList<[Var, Field]>;
|
||||
let Documentation = [NonStringDocs];
|
||||
}
|
||||
|
||||
def ModularFormat : InheritableAttr {
|
||||
let Spellings = [Clang<"modular_format">];
|
||||
let Args = [
|
||||
IdentifierArgument<"ModularImplFn">,
|
||||
StringArgument<"ImplName">,
|
||||
VariadicStringArgument<"Aspects">
|
||||
];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [ModularFormatDocs];
|
||||
}
|
||||
|
@ -9549,3 +9549,28 @@ silence diagnostics with code like:
|
||||
__attribute__((nonstring)) char NotAStr[3] = "foo"; // Not diagnosed
|
||||
}];
|
||||
}
|
||||
|
||||
def ModularFormatDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``modular_format`` attribute can be applied to a function that bears the
|
||||
``format`` attribute to indicate that the implementation is modular on the
|
||||
format string argument. When the format argument for a given call is constant,
|
||||
the compiler may redirect the call to the symbol given as the first argument to
|
||||
the attribute (the modular implementation function).
|
||||
|
||||
The second argument is a implementation name, and the remaining arguments are
|
||||
aspects of the format string for the compiler to report. If the compiler does
|
||||
not understand a aspect, it must summarily report that the format string has
|
||||
that aspect.
|
||||
|
||||
The compiler reports an aspect by issing a relocation for the symbol
|
||||
`<impl_name>_<aspect>``. This arranges for code and data needed to support the
|
||||
aspect of the implementation to be brought into the link to satisfy weak
|
||||
references in the modular implemenation function.
|
||||
|
||||
The following aspects are currently supported:
|
||||
|
||||
- ``float``: The call has a floating point argument
|
||||
}];
|
||||
}
|
||||
|
@ -2560,6 +2560,18 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
|
||||
|
||||
if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>())
|
||||
FuncAttrs.addAttribute("aarch64_pstate_sm_body");
|
||||
|
||||
if (auto *ModularFormat = TargetDecl->getAttr<ModularFormatAttr>()) {
|
||||
// TODO: Error checking
|
||||
FormatAttr *Format = TargetDecl->getAttr<FormatAttr>();
|
||||
std::string FormatIdx = std::to_string(Format->getFormatIdx());
|
||||
std::string FirstArg = std::to_string(Format->getFirstArg());
|
||||
SmallVector<StringRef> Args = {
|
||||
FormatIdx, FirstArg, ModularFormat->getModularImplFn()->getName(),
|
||||
ModularFormat->getImplName()};
|
||||
llvm::append_range(Args, ModularFormat->aspects());
|
||||
FuncAttrs.addAttribute("modular-format", llvm::join(Args, ","));
|
||||
}
|
||||
}
|
||||
|
||||
// Attach "no-builtins" attributes to:
|
||||
|
@ -6752,6 +6752,29 @@ static void handleVTablePointerAuthentication(Sema &S, Decl *D,
|
||||
CustomDiscriminationValue));
|
||||
}
|
||||
|
||||
static void handleModularFormat(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
StringRef ImplName;
|
||||
if (!S.checkStringLiteralArgumentAttr(AL, 1, ImplName))
|
||||
return;
|
||||
SmallVector<StringRef> Aspects;
|
||||
for (unsigned I = 2, E = AL.getNumArgs(); I != E; ++I) {
|
||||
StringRef Aspect;
|
||||
if (!S.checkStringLiteralArgumentAttr(AL, I, Aspect))
|
||||
return;
|
||||
Aspects.push_back(Aspect);
|
||||
}
|
||||
|
||||
// Store aspects sorted and without duplicates.
|
||||
llvm::sort(Aspects);
|
||||
Aspects.erase(llvm::unique(Aspects), Aspects.end());
|
||||
|
||||
// TODO: Type checking on identifier
|
||||
// TODO: Merge attributes
|
||||
D->addAttr(::new (S.Context) ModularFormatAttr(
|
||||
S.Context, AL, AL.getArgAsIdent(0)->getIdentifierInfo(), ImplName,
|
||||
Aspects.data(), Aspects.size()));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Level Sema Entry Points
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -7679,6 +7702,10 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
|
||||
case ParsedAttr::AT_VTablePointerAuthentication:
|
||||
handleVTablePointerAuthentication(S, D, AL);
|
||||
break;
|
||||
|
||||
case ParsedAttr::AT_ModularFormat:
|
||||
handleModularFormat(S, D, AL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user