Skip to content

Commit 7adc2bd

Browse files
committed
[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.
1 parent 9dff0b3 commit 7adc2bd

File tree

4 files changed

+75
-0
lines changed

4 files changed

+75
-0
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5240,3 +5240,14 @@ def NonString : InheritableAttr {
52405240
let Subjects = SubjectList<[Var, Field]>;
52415241
let Documentation = [NonStringDocs];
52425242
}
5243+
5244+
def ModularFormat : InheritableAttr {
5245+
let Spellings = [Clang<"modular_format">];
5246+
let Args = [
5247+
IdentifierArgument<"ModularImplFn">,
5248+
StringArgument<"ImplName">,
5249+
VariadicStringArgument<"Aspects">
5250+
];
5251+
let Subjects = SubjectList<[Function]>;
5252+
let Documentation = [ModularFormatDocs];
5253+
}

clang/include/clang/Basic/AttrDocs.td

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9605,3 +9605,28 @@ silence diagnostics with code like:
96059605
__attribute__((nonstring)) char NotAStr[3] = "foo"; // Not diagnosed
96069606
}];
96079607
}
9608+
9609+
def ModularFormatDocs : Documentation {
9610+
let Category = DocCatFunction;
9611+
let Content = [{
9612+
The ``modular_format`` attribute can be applied to a function that bears the
9613+
``format`` attribute to indicate that the implementation is modular on the
9614+
format string argument. When the format argument for a given call is constant,
9615+
the compiler may redirect the call to the symbol given as the first argument to
9616+
the attribute (the modular implementation function).
9617+
9618+
The second argument is a implementation name, and the remaining arguments are
9619+
aspects of the format string for the compiler to report. If the compiler does
9620+
not understand a aspect, it must summarily report that the format string has
9621+
that aspect.
9622+
9623+
The compiler reports an aspect by issing a relocation for the symbol
9624+
`<impl_name>_<aspect>``. This arranges for code and data needed to support the
9625+
aspect of the implementation to be brought into the link to satisfy weak
9626+
references in the modular implemenation function.
9627+
9628+
The following aspects are currently supported:
9629+
9630+
- ``float``: The call has a floating point argument
9631+
}];
9632+
}

clang/lib/CodeGen/CGCall.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2560,6 +2560,18 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
25602560

25612561
if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>())
25622562
FuncAttrs.addAttribute("aarch64_pstate_sm_body");
2563+
2564+
if (auto *ModularFormat = TargetDecl->getAttr<ModularFormatAttr>()) {
2565+
// TODO: Error checking
2566+
FormatAttr *Format = TargetDecl->getAttr<FormatAttr>();
2567+
std::string FormatIdx = std::to_string(Format->getFormatIdx());
2568+
std::string FirstArg = std::to_string(Format->getFirstArg());
2569+
SmallVector<StringRef> Args = {
2570+
FormatIdx, FirstArg, ModularFormat->getModularImplFn()->getName(),
2571+
ModularFormat->getImplName()};
2572+
llvm::append_range(Args, ModularFormat->aspects());
2573+
FuncAttrs.addAttribute("modular-format", llvm::join(Args, ","));
2574+
}
25632575
}
25642576

25652577
// Attach "no-builtins" attributes to:

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6751,6 +6751,29 @@ static void handleVTablePointerAuthentication(Sema &S, Decl *D,
67516751
CustomDiscriminationValue));
67526752
}
67536753

6754+
static void handleModularFormat(Sema &S, Decl *D, const ParsedAttr &AL) {
6755+
StringRef ImplName;
6756+
if (!S.checkStringLiteralArgumentAttr(AL, 1, ImplName))
6757+
return;
6758+
SmallVector<StringRef> Aspects;
6759+
for (unsigned I = 2, E = AL.getNumArgs(); I != E; ++I) {
6760+
StringRef Aspect;
6761+
if (!S.checkStringLiteralArgumentAttr(AL, I, Aspect))
6762+
return;
6763+
Aspects.push_back(Aspect);
6764+
}
6765+
6766+
// Store aspects sorted and without duplicates.
6767+
llvm::sort(Aspects);
6768+
Aspects.erase(llvm::unique(Aspects), Aspects.end());
6769+
6770+
// TODO: Type checking on identifier
6771+
// TODO: Merge attributes
6772+
D->addAttr(::new (S.Context) ModularFormatAttr(
6773+
S.Context, AL, AL.getArgAsIdent(0)->getIdentifierInfo(), ImplName,
6774+
Aspects.data(), Aspects.size()));
6775+
}
6776+
67546777
//===----------------------------------------------------------------------===//
67556778
// Top Level Sema Entry Points
67566779
//===----------------------------------------------------------------------===//
@@ -7681,6 +7704,10 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
76817704
case ParsedAttr::AT_VTablePointerAuthentication:
76827705
handleVTablePointerAuthentication(S, D, AL);
76837706
break;
7707+
7708+
case ParsedAttr::AT_ModularFormat:
7709+
handleModularFormat(S, D, AL);
7710+
break;
76847711
}
76857712
}
76867713

0 commit comments

Comments
 (0)