summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp68
1 files changed, 66 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 25632e63e7b..950dcac1bbc 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2954,8 +2954,7 @@ static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
(ParmType->isBooleanType() ||
!ParmType->isIntegralType(S.getASTContext()))) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_vec_type_hint)
- << ParmType;
+ S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << 3 << AL;
return;
}
@@ -4555,6 +4554,67 @@ static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
DiagnosticIdentifiers.size(), AL.getAttributeSpellingListIndex()));
}
+static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ TypeSourceInfo *DerefTypeLoc = nullptr;
+ QualType ParmType;
+ if (AL.hasParsedType()) {
+ ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc);
+
+ unsigned SelectIdx = ~0U;
+ if (ParmType->isVoidType())
+ SelectIdx = 0;
+ else if (ParmType->isReferenceType())
+ SelectIdx = 1;
+ else if (ParmType->isArrayType())
+ SelectIdx = 2;
+
+ if (SelectIdx != ~0U) {
+ S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument)
+ << SelectIdx << AL;
+ return;
+ }
+ }
+
+ // To check if earlier decl attributes do not conflict the newly parsed ones
+ // we always add (and check) the attribute to the cannonical decl.
+ D = D->getCanonicalDecl();
+ if (AL.getKind() == ParsedAttr::AT_Owner) {
+ if (checkAttrMutualExclusion<PointerAttr>(S, D, AL))
+ return;
+ if (const auto *OAttr = D->getAttr<OwnerAttr>()) {
+ const Type *ExistingDerefType = OAttr->getDerefTypeLoc()
+ ? OAttr->getDerefType().getTypePtr()
+ : nullptr;
+ if (ExistingDerefType != ParmType.getTypePtrOrNull()) {
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+ << AL << OAttr;
+ S.Diag(OAttr->getLocation(), diag::note_conflicting_attribute);
+ }
+ return;
+ }
+ D->addAttr(::new (S.Context)
+ OwnerAttr(AL.getRange(), S.Context, DerefTypeLoc,
+ AL.getAttributeSpellingListIndex()));
+ } else {
+ if (checkAttrMutualExclusion<OwnerAttr>(S, D, AL))
+ return;
+ if (const auto *PAttr = D->getAttr<PointerAttr>()) {
+ const Type *ExistingDerefType = PAttr->getDerefTypeLoc()
+ ? PAttr->getDerefType().getTypePtr()
+ : nullptr;
+ if (ExistingDerefType != ParmType.getTypePtrOrNull()) {
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+ << AL << PAttr;
+ S.Diag(PAttr->getLocation(), diag::note_conflicting_attribute);
+ }
+ return;
+ }
+ D->addAttr(::new (S.Context)
+ PointerAttr(AL.getRange(), S.Context, DerefTypeLoc,
+ AL.getAttributeSpellingListIndex()));
+ }
+}
+
bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
const FunctionDecl *FD) {
if (Attrs.isInvalid())
@@ -7158,6 +7218,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Suppress:
handleSuppressAttr(S, D, AL);
break;
+ case ParsedAttr::AT_Owner:
+ case ParsedAttr::AT_Pointer:
+ handleLifetimeCategoryAttr(S, D, AL);
+ break;
case ParsedAttr::AT_OpenCLKernel:
handleSimpleAttribute<OpenCLKernelAttr>(S, D, AL);
break;
OpenPOWER on IntegriCloud