Skip to content

Commit 006f67b

Browse files
committed
Merge from 'main' to 'sycl-web' (7 commits)
CONFLICT (content): Merge conflict in clang/lib/Sema/SemaDeclAttr.cpp
2 parents f3dcc42 + 665da18 commit 006f67b

File tree

24 files changed

+792
-68
lines changed

24 files changed

+792
-68
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,9 @@ Attribute Changes in Clang
362362
- When the ``weak`` attribute is applied to a const qualified variable clang no longer
363363
tells the backend it is allowed to optimize based on initializer value.
364364

365+
- Added the ``clang::annotate_type`` attribute, which can be used to add
366+
annotations to types (see documentation for details).
367+
365368
Windows Support
366369
---------------
367370

clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,14 @@ def Annotate : InheritableParamAttr {
826826
let Documentation = [Undocumented];
827827
}
828828

829+
def AnnotateType : TypeAttr {
830+
let Spellings = [CXX11<"clang", "annotate_type">, C2x<"clang", "annotate_type">];
831+
let Args = [StringArgument<"Annotation">, VariadicExprArgument<"Args">];
832+
let HasCustomParsing = 1;
833+
let AcceptsExprPack = 1;
834+
let Documentation = [AnnotateTypeDocs];
835+
}
836+
829837
def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
830838
// NOTE: If you add any additional spellings, M68kInterrupt's,
831839
// MSP430Interrupt's, MipsInterrupt's and AnyX86Interrupt's spellings

clang/include/clang/Basic/AttrDocs.td

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8120,6 +8120,40 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo
81208120
}];
81218121
}
81228122

8123+
def AnnotateTypeDocs : Documentation {
8124+
let Category = DocCatType;
8125+
let Heading = "annotate_type";
8126+
let Content = [{
8127+
This attribute is used to add annotations to types, typically for use by static
8128+
analysis tools that are not integrated into the core Clang compiler (e.g.,
8129+
Clang-Tidy checks or out-of-tree Clang-based tools). It is a counterpart to the
8130+
`annotate` attribute, which serves the same purpose, but for declarations.
8131+
8132+
The attribute takes a mandatory string literal argument specifying the
8133+
annotation category and an arbitrary number of optional arguments that provide
8134+
additional information specific to the annotation category. The optional
8135+
arguments must be constant expressions of arbitrary type.
8136+
8137+
For example:
8138+
8139+
.. code-block:: c++
8140+
8141+
int* [[clang::annotate("category1", "foo", 1)]] f(int[[clang::annotate("category2")]] *);
8142+
8143+
The attribute does not have any effect on the semantics of the type system,
8144+
neither type checking rules, nor runtime semantics. In particular:
8145+
8146+
- ``std::is_same<T, T [[clang::annotate_type("foo")]]`` is true for all types
8147+
``T``.
8148+
8149+
- It is not permissible for overloaded functions or template specializations
8150+
to differ merely by an ``annotate_type`` attribute.
8151+
8152+
- The presence of an ``annotate_type`` attribute will not affect name
8153+
mangling.
8154+
}];
8155+
}
8156+
81238157
def WeakDocs : Documentation {
81248158
let Category = DocCatDecl;
81258159
let Content = [{

clang/include/clang/Sema/Sema.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10769,6 +10769,13 @@ class Sema final {
1076910769
void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
1077010770
StringRef Annot, MutableArrayRef<Expr *> Args);
1077110771

10772+
/// ConstantFoldAttrArgs - Folds attribute arguments into ConstantExprs
10773+
/// (unless they are value dependent or type dependent). Returns false
10774+
/// and emits a diagnostic if one or more of the arguments could not be
10775+
/// folded into a constant.
10776+
bool ConstantFoldAttrArgs(const AttributeCommonInfo &CI,
10777+
MutableArrayRef<Expr *> Args);
10778+
1077210779
/// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
1077310780
/// declaration.
1077410781
void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,

clang/lib/AST/TypePrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,6 +1721,15 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
17211721
if (T->getAttrKind() == attr::AddressSpace)
17221722
return;
17231723

1724+
if (T->getAttrKind() == attr::AnnotateType) {
1725+
// FIXME: Print the attribute arguments once we have a way to retrieve these
1726+
// here. For the meantime, we just print `[[clang::annotate_type(...)]]`
1727+
// without the arguments so that we know at least that we had _some_
1728+
// annotation on the type.
1729+
OS << " [[clang::annotate_type(...)]]";
1730+
return;
1731+
}
1732+
17241733
OS << " __attribute__((";
17251734
switch (T->getAttrKind()) {
17261735
#define TYPE_ATTR(NAME)
@@ -1762,6 +1771,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
17621771
case attr::UPtr:
17631772
case attr::AddressSpace:
17641773
case attr::CmseNSCall:
1774+
case attr::AnnotateType:
17651775
llvm_unreachable("This attribute should have been handled already");
17661776

17671777
case attr::NSReturnsRetained:

clang/lib/Parse/ParseDecl.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3177,10 +3177,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
31773177
if (!AttrsLastTime)
31783178
ProhibitAttributes(attrs);
31793179
else {
3180-
// Reject C++11 attributes that appertain to decl specifiers as
3181-
// we don't support any C++11 attributes that appertain to decl
3182-
// specifiers. This also conforms to what g++ 4.8 is doing.
3183-
ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr);
3180+
// Reject most C++11 / C2x attributes on the decl-specifier-seq, but
3181+
// allow `annotate_type` as a special case.
3182+
// FIXME: We should more generally allow type attributes to be placed
3183+
// on the decl-specifier-seq; https://reviews.llvm.org/D126061 will
3184+
// make this change.
3185+
for (const ParsedAttr &PA : attrs) {
3186+
if (!PA.isCXX11Attribute() && !PA.isC2xAttribute())
3187+
continue;
3188+
if (PA.getKind() == ParsedAttr::UnknownAttribute)
3189+
// We will warn about the unknown attribute elsewhere (in
3190+
// SemaDeclAttr.cpp)
3191+
continue;
3192+
if (PA.getKind() == ParsedAttr::AT_AnnotateType)
3193+
continue;
3194+
Diag(PA.getLoc(), diag::err_attribute_not_type_attr) << PA;
3195+
PA.setInvalid();
3196+
}
31843197

31853198
DS.takeAttributesFrom(attrs);
31863199
}

clang/lib/Sema/SemaAttr.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,54 @@ void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
384384
AlignPackStack.Act(PragmaLoc, Action, SlotLabel, Info);
385385
}
386386

387+
bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI,
388+
MutableArrayRef<Expr *> Args) {
389+
llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
390+
for (unsigned Idx = 0; Idx < Args.size(); Idx++) {
391+
Expr *&E = Args.begin()[Idx];
392+
assert(E && "error are handled before");
393+
if (E->isValueDependent() || E->isTypeDependent())
394+
continue;
395+
396+
// FIXME: Use DefaultFunctionArrayLValueConversion() in place of the logic
397+
// that adds implicit casts here.
398+
if (E->getType()->isArrayType())
399+
E = ImpCastExprToType(E, Context.getPointerType(E->getType()),
400+
clang::CK_ArrayToPointerDecay)
401+
.get();
402+
if (E->getType()->isFunctionType())
403+
E = ImplicitCastExpr::Create(Context,
404+
Context.getPointerType(E->getType()),
405+
clang::CK_FunctionToPointerDecay, E, nullptr,
406+
VK_PRValue, FPOptionsOverride());
407+
if (E->isLValue())
408+
E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),
409+
clang::CK_LValueToRValue, E, nullptr,
410+
VK_PRValue, FPOptionsOverride());
411+
412+
Expr::EvalResult Eval;
413+
Notes.clear();
414+
Eval.Diag = &Notes;
415+
416+
bool Result = E->EvaluateAsConstantExpr(Eval, Context);
417+
418+
/// Result means the expression can be folded to a constant.
419+
/// Note.empty() means the expression is a valid constant expression in the
420+
/// current language mode.
421+
if (!Result || !Notes.empty()) {
422+
Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)
423+
<< CI << (Idx + 1) << AANT_ArgumentConstantExpr;
424+
for (auto &Note : Notes)
425+
Diag(Note.first, Note.second);
426+
return false;
427+
}
428+
assert(Eval.Val.hasValue());
429+
E = ConstantExpr::Create(Context, E, Eval.Val);
430+
}
431+
432+
return true;
433+
}
434+
387435
void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,
388436
SourceLocation IncludeLoc) {
389437
if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) {

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5375,48 +5375,10 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
53755375
void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
53765376
StringRef Str, MutableArrayRef<Expr *> Args) {
53775377
auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI);
5378-
llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
5379-
for (unsigned Idx = 0; Idx < Attr->args_size(); Idx++) {
5380-
Expr *&E = Attr->args_begin()[Idx];
5381-
assert(E && "error are handled before");
5382-
if (E->isValueDependent() || E->isTypeDependent())
5383-
continue;
5384-
5385-
if (E->getType()->isArrayType())
5386-
E = ImpCastExprToType(E, Context.getPointerType(E->getType()),
5387-
clang::CK_ArrayToPointerDecay)
5388-
.get();
5389-
if (E->getType()->isFunctionType())
5390-
E = ImplicitCastExpr::Create(Context,
5391-
Context.getPointerType(E->getType()),
5392-
clang::CK_FunctionToPointerDecay, E, nullptr,
5393-
VK_PRValue, FPOptionsOverride());
5394-
if (E->isLValue())
5395-
E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),
5396-
clang::CK_LValueToRValue, E, nullptr,
5397-
VK_PRValue, FPOptionsOverride());
5398-
5399-
Expr::EvalResult Eval;
5400-
Notes.clear();
5401-
Eval.Diag = &Notes;
5402-
5403-
bool Result =
5404-
E->EvaluateAsConstantExpr(Eval, Context);
5405-
5406-
/// Result means the expression can be folded to a constant.
5407-
/// Note.empty() means the expression is a valid constant expression in the
5408-
/// current language mode.
5409-
if (!Result || !Notes.empty()) {
5410-
Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)
5411-
<< CI << (Idx + 1) << AANT_ArgumentConstantExpr;
5412-
for (auto &Note : Notes)
5413-
Diag(Note.first, Note.second);
5414-
return;
5415-
}
5416-
assert(Eval.Val.hasValue());
5417-
E = ConstantExpr::Create(Context, E, Eval.Val);
5378+
if (ConstantFoldAttrArgs(
5379+
CI, MutableArrayRef<Expr *>(Attr->args_begin(), Attr->args_end()))) {
5380+
D->addAttr(Attr);
54185381
}
5419-
D->addAttr(Attr);
54205382
}
54215383

54225384
static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

clang/lib/Sema/SemaType.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8227,6 +8227,34 @@ static void HandleMatrixTypeAttr(QualType &CurType, const ParsedAttr &Attr,
82278227
CurType = T;
82288228
}
82298229

8230+
static void HandleAnnotateTypeAttr(TypeProcessingState &State,
8231+
QualType &CurType, const ParsedAttr &PA) {
8232+
Sema &S = State.getSema();
8233+
8234+
if (PA.getNumArgs() < 1) {
8235+
S.Diag(PA.getLoc(), diag::err_attribute_too_few_arguments) << PA << 1;
8236+
return;
8237+
}
8238+
8239+
// Make sure that there is a string literal as the annotation's first
8240+
// argument.
8241+
StringRef Str;
8242+
if (!S.checkStringLiteralArgumentAttr(PA, 0, Str))
8243+
return;
8244+
8245+
llvm::SmallVector<Expr *, 4> Args;
8246+
Args.reserve(PA.getNumArgs() - 1);
8247+
for (unsigned Idx = 1; Idx < PA.getNumArgs(); Idx++) {
8248+
assert(!PA.isArgIdent(Idx));
8249+
Args.push_back(PA.getArgAsExpr(Idx));
8250+
}
8251+
if (!S.ConstantFoldAttrArgs(PA, Args))
8252+
return;
8253+
auto *AnnotateTypeAttr =
8254+
AnnotateTypeAttr::Create(S.Context, Str, Args.data(), Args.size(), PA);
8255+
CurType = State.getAttributedType(AnnotateTypeAttr, CurType, CurType);
8256+
}
8257+
82308258
static void HandleLifetimeBoundAttr(TypeProcessingState &State,
82318259
QualType &CurType,
82328260
ParsedAttr &Attr) {
@@ -8289,10 +8317,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
82898317
if (!IsTypeAttr)
82908318
continue;
82918319
}
8292-
} else if (TAL != TAL_DeclChunk && !isAddressSpaceKind(attr)) {
8320+
} else if (TAL != TAL_DeclChunk && !isAddressSpaceKind(attr) &&
8321+
attr.getKind() != ParsedAttr::AT_AnnotateType) {
82938322
// Otherwise, only consider type processing for a C++11 attribute if
82948323
// it's actually been applied to a type.
8295-
// We also allow C++11 address_space and
8324+
// We also allow C++11 address_space and annotate_type and
82968325
// OpenCL language address space attributes to pass through.
82978326
continue;
82988327
}
@@ -8496,6 +8525,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
84968525
attr.setUsedAsTypeAttr();
84978526
break;
84988527
}
8528+
case ParsedAttr::AT_AnnotateType: {
8529+
HandleAnnotateTypeAttr(state, type, attr);
8530+
attr.setUsedAsTypeAttr();
8531+
break;
8532+
}
84998533
}
85008534

85018535
// Handle attributes that are defined in a macro. We do not want this to be

clang/test/AST/attr-annotate-type.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 %s -ast-dump -fdouble-square-bracket-attributes | FileCheck %s
2+
3+
// Verify that we print the [[clang::annotate_type]] attribute.
4+
// FIXME: The arguments are currently not printed -- see also comments in
5+
// TypePrinter.cpp.
6+
7+
// Need to escape the `[[` as a regex to avoid it being interpreted as a
8+
// substitution block.
9+
// CHECK: VarDecl {{.*}} x1 'int {{\[\[}}clang::annotate_type(...){{]]}}':'int'
10+
int [[clang::annotate_type("bar")]] x1;
11+
// CHECK: VarDecl {{.*}} x2 'int * {{\[\[}}clang::annotate_type(...){{]]}}':'int *'
12+
int *[[clang::annotate_type("bar")]] x2;

0 commit comments

Comments
 (0)