Skip to content

Commit d3205bb

Browse files
committed
[Annotation] Allows annotation to carry some additional constant arguments.
This allows using annotation in a much more contexts than it currently has. especially when annotation with template or constexpr. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D88645
1 parent 8aa60f6 commit d3205bb

31 files changed

+480
-79
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ def AnalyzerNoReturn : InheritableAttr {
737737

738738
def Annotate : InheritableParamAttr {
739739
let Spellings = [Clang<"annotate">];
740-
let Args = [StringArgument<"Annotation">];
740+
let Args = [StringArgument<"Annotation">, VariadicExprArgument<"Args">];
741741
// Ensure that the annotate attribute can be used with
742742
// '#pragma clang attribute' even though it has no subject list.
743743
let PragmaAttributeSupport = 1;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2860,7 +2860,7 @@ def err_attribute_sizeless_type : Error<
28602860
"%0 attribute cannot be applied to sizeless type %1">;
28612861
def err_attribute_argument_n_type : Error<
28622862
"%0 attribute requires parameter %1 to be %select{int or bool|an integer "
2863-
"constant|a string|an identifier}2">;
2863+
"constant|a string|an identifier|a constant expression}2">;
28642864
def err_attribute_argument_type : Error<
28652865
"%0 attribute requires %select{int or bool|an integer "
28662866
"constant|a string|an identifier}1">;

clang/include/clang/Sema/ParsedAttr.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,8 @@ enum AttributeArgumentNType {
10231023
AANT_ArgumentIntOrBool,
10241024
AANT_ArgumentIntegerConstant,
10251025
AANT_ArgumentString,
1026-
AANT_ArgumentIdentifier
1026+
AANT_ArgumentIdentifier,
1027+
AANT_ArgumentConstantExpr,
10271028
};
10281029

10291030
/// These constants match the enumerated choices of
@@ -1058,6 +1059,31 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
10581059
return DB;
10591060
}
10601061

1062+
/// AttributeCommonInfo has a non-explicit constructor which takes an
1063+
/// SourceRange as its only argument, this constructor has many uses so making
1064+
/// it explicit is hard. This constructor causes ambiguity with
1065+
/// DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, SourceRange R).
1066+
/// We use SFINAE to disable any conversion and remove any ambiguity.
1067+
template <typename ACI,
1068+
typename std::enable_if_t<
1069+
std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
1070+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1071+
const ACI &CI) {
1072+
DB.AddTaggedVal(reinterpret_cast<intptr_t>(CI.getAttrName()),
1073+
DiagnosticsEngine::ak_identifierinfo);
1074+
return DB;
1075+
}
1076+
1077+
template <typename ACI,
1078+
typename std::enable_if_t<
1079+
std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
1080+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1081+
const ACI* CI) {
1082+
DB.AddTaggedVal(reinterpret_cast<intptr_t>(CI->getAttrName()),
1083+
DiagnosticsEngine::ak_identifierinfo);
1084+
return DB;
1085+
}
1086+
10611087
} // namespace clang
10621088

10631089
#endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9987,6 +9987,10 @@ class Sema final {
99879987
/// declaration.
99889988
void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
99899989

9990+
/// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D.
9991+
void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
9992+
StringRef Annot, MutableArrayRef<Expr *> Args);
9993+
99909994
/// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
99919995
/// declaration.
99929996
void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3403,7 +3403,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
34033403
// non-wide string literal, potentially casted, so the cast<> is safe.
34043404
const Expr *AnnotationStrExpr = E->getArg(1)->IgnoreParenCasts();
34053405
StringRef Str = cast<StringLiteral>(AnnotationStrExpr)->getString();
3406-
return RValue::get(EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc()));
3406+
return RValue::get(
3407+
EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc(), nullptr));
34073408
}
34083409
case Builtin::BI__builtin_addcb:
34093410
case Builtin::BI__builtin_addcs:

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,13 +2234,16 @@ void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue,
22342234
llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Function *AnnotationFn,
22352235
llvm::Value *AnnotatedVal,
22362236
StringRef AnnotationStr,
2237-
SourceLocation Location) {
2238-
llvm::Value *Args[4] = {
2239-
AnnotatedVal,
2240-
Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy),
2241-
Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
2242-
CGM.EmitAnnotationLineNo(Location)
2237+
SourceLocation Location,
2238+
const AnnotateAttr *Attr) {
2239+
SmallVector<llvm::Value *, 5> Args = {
2240+
AnnotatedVal,
2241+
Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy),
2242+
Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
2243+
CGM.EmitAnnotationLineNo(Location),
22432244
};
2245+
if (Attr)
2246+
Args.push_back(CGM.EmitAnnotationArgs(Attr));
22442247
return Builder.CreateCall(AnnotationFn, Args);
22452248
}
22462249

@@ -2251,7 +2254,7 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) {
22512254
for (const auto *I : D->specific_attrs<AnnotateAttr>())
22522255
EmitAnnotationCall(CGM.getIntrinsic(llvm::Intrinsic::var_annotation),
22532256
Builder.CreateBitCast(V, CGM.Int8PtrTy, V->getName()),
2254-
I->getAnnotation(), D->getLocation());
2257+
I->getAnnotation(), D->getLocation(), I);
22552258
}
22562259

22572260
Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
@@ -2268,7 +2271,7 @@ Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
22682271
// itself.
22692272
if (VTy != CGM.Int8PtrTy)
22702273
V = Builder.CreateBitCast(V, CGM.Int8PtrTy);
2271-
V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation());
2274+
V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation(), I);
22722275
V = Builder.CreateBitCast(V, VTy);
22732276
}
22742277

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4326,7 +4326,8 @@ class CodeGenFunction : public CodeGenTypeCache {
43264326
llvm::Value *EmitAnnotationCall(llvm::Function *AnnotationFn,
43274327
llvm::Value *AnnotatedVal,
43284328
StringRef AnnotationStr,
4329-
SourceLocation Location);
4329+
SourceLocation Location,
4330+
const AnnotateAttr *Attr);
43304331

43314332
/// Emit local annotations for the local variable V, declared by D.
43324333
void EmitVarAnnotations(const VarDecl *D, llvm::Value *V);

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,13 +2341,48 @@ llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) {
23412341
return llvm::ConstantInt::get(Int32Ty, LineNo);
23422342
}
23432343

2344+
llvm::Constant *CodeGenModule::EmitAnnotationArgs(const AnnotateAttr *Attr) {
2345+
ArrayRef<Expr *> Exprs = {Attr->args_begin(), Attr->args_size()};
2346+
Exprs = Exprs.drop_front();
2347+
if (Exprs.empty())
2348+
return llvm::ConstantPointerNull::get(Int8PtrTy);
2349+
2350+
llvm::FoldingSetNodeID ID;
2351+
for (Expr *E : Exprs) {
2352+
ID.Add(cast<clang::ConstantExpr>(E)->getAPValueResult());
2353+
}
2354+
llvm::Constant *&Lookup = AnnotationArgs[ID.ComputeHash()];
2355+
if (Lookup)
2356+
return Lookup;
2357+
2358+
llvm::SmallVector<llvm::Constant *, 4> LLVMArgs;
2359+
LLVMArgs.reserve(Exprs.size());
2360+
ConstantEmitter ConstEmiter(*this);
2361+
llvm::transform(Exprs, std::back_inserter(LLVMArgs), [&](const Expr *E) {
2362+
const auto *CE = cast<clang::ConstantExpr>(E);
2363+
return ConstEmiter.emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(),
2364+
CE->getType());
2365+
});
2366+
auto *Struct = llvm::ConstantStruct::getAnon(LLVMArgs);
2367+
auto *GV = new llvm::GlobalVariable(getModule(), Struct->getType(), true,
2368+
llvm::GlobalValue::PrivateLinkage, Struct,
2369+
".args");
2370+
GV->setSection(AnnotationSection);
2371+
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2372+
auto *Bitcasted = llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
2373+
2374+
Lookup = Bitcasted;
2375+
return Bitcasted;
2376+
}
2377+
23442378
llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
23452379
const AnnotateAttr *AA,
23462380
SourceLocation L) {
23472381
// Get the globals for file name, annotation, and the line number.
23482382
llvm::Constant *AnnoGV = EmitAnnotationString(AA->getAnnotation()),
23492383
*UnitGV = EmitAnnotationUnit(L),
2350-
*LineNoCst = EmitAnnotationLineNo(L);
2384+
*LineNoCst = EmitAnnotationLineNo(L),
2385+
*Args = EmitAnnotationArgs(AA);
23512386

23522387
llvm::Constant *ASZeroGV = GV;
23532388
if (GV->getAddressSpace() != 0) {
@@ -2356,11 +2391,12 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
23562391
}
23572392

23582393
// Create the ConstantStruct for the global annotation.
2359-
llvm::Constant *Fields[4] = {
2360-
llvm::ConstantExpr::getBitCast(ASZeroGV, Int8PtrTy),
2361-
llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy),
2362-
llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy),
2363-
LineNoCst
2394+
llvm::Constant *Fields[] = {
2395+
llvm::ConstantExpr::getBitCast(ASZeroGV, Int8PtrTy),
2396+
llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy),
2397+
llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy),
2398+
LineNoCst,
2399+
Args,
23642400
};
23652401
return llvm::ConstantStruct::getAnon(Fields);
23662402
}

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,9 @@ class CodeGenModule : public CodeGenTypeCache {
413413
/// Map used to get unique annotation strings.
414414
llvm::StringMap<llvm::Constant*> AnnotationStrings;
415415

416+
/// Used for uniquing of annotation arguments.
417+
llvm::DenseMap<unsigned, llvm::Constant *> AnnotationArgs;
418+
416419
llvm::StringMap<llvm::GlobalVariable *> CFConstantStringMap;
417420

418421
llvm::DenseMap<llvm::Constant *, llvm::GlobalVariable *> ConstantStringMap;
@@ -1241,6 +1244,9 @@ class CodeGenModule : public CodeGenTypeCache {
12411244
/// Emit the annotation line number.
12421245
llvm::Constant *EmitAnnotationLineNo(SourceLocation L);
12431246

1247+
/// Emit additional args of the annotation.
1248+
llvm::Constant *EmitAnnotationArgs(const AnnotateAttr *Attr);
1249+
12441250
/// Generate the llvm::ConstantStruct which contains the annotation
12451251
/// information for a given GlobalValue. The annotation struct is
12461252
/// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,20 +3682,68 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
36823682
RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL));
36833683
}
36843684

3685+
void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
3686+
StringRef Str, MutableArrayRef<Expr *> Args) {
3687+
auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI);
3688+
llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
3689+
for (unsigned Idx = 1; Idx < Attr->args_size(); Idx++) {
3690+
Expr *&E = Attr->args_begin()[Idx];
3691+
assert(E && "error are handled before");
3692+
if (E->isValueDependent() || E->isTypeDependent())
3693+
continue;
3694+
3695+
if (E->getType()->isArrayType())
3696+
E = ImpCastExprToType(E, Context.getPointerType(E->getType()),
3697+
clang::CK_ArrayToPointerDecay)
3698+
.get();
3699+
if (E->getType()->isFunctionType())
3700+
E = ImplicitCastExpr::Create(Context,
3701+
Context.getPointerType(E->getType()),
3702+
clang::CK_FunctionToPointerDecay, E, nullptr,
3703+
VK_RValue, FPOptionsOverride());
3704+
if (E->isLValue())
3705+
E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),
3706+
clang::CK_LValueToRValue, E, nullptr,
3707+
VK_RValue, FPOptionsOverride());
3708+
3709+
Expr::EvalResult Eval;
3710+
Notes.clear();
3711+
Eval.Diag = &Notes;
3712+
3713+
bool Result =
3714+
E->EvaluateAsConstantExpr(Eval, Context);
3715+
3716+
/// Result means the expression can be folded to a constant.
3717+
/// Note.empty() means the expression is a valid constant expression in the
3718+
/// current language mode.
3719+
if (!Result || !Notes.empty()) {
3720+
Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)
3721+
<< CI << Idx << AANT_ArgumentConstantExpr;
3722+
for (auto &Note : Notes)
3723+
Diag(Note.first, Note.second);
3724+
return;
3725+
}
3726+
assert(Eval.Val.hasValue());
3727+
E = ConstantExpr::Create(Context, E, Eval.Val);
3728+
}
3729+
D->addAttr(Attr);
3730+
}
3731+
36853732
static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3686-
// Make sure that there is a string literal as the annotation's single
3733+
// Make sure that there is a string literal as the annotation's first
36873734
// argument.
36883735
StringRef Str;
36893736
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
36903737
return;
36913738

3692-
// Don't duplicate annotations that are already set.
3693-
for (const auto *I : D->specific_attrs<AnnotateAttr>()) {
3694-
if (I->getAnnotation() == Str)
3695-
return;
3739+
llvm::SmallVector<Expr *, 4> Args;
3740+
Args.reserve(AL.getNumArgs());
3741+
for (unsigned Idx = 0; Idx < AL.getNumArgs(); Idx++) {
3742+
assert(!AL.isArgIdent(Idx));
3743+
Args.push_back(AL.getArgAsExpr(Idx));
36963744
}
36973745

3698-
D->addAttr(::new (S.Context) AnnotateAttr(S.Context, AL, Str));
3746+
S.AddAnnotationAttr(D, AL, Str, Args);
36993747
}
37003748

37013749
static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

0 commit comments

Comments
 (0)