summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--lib/Sema/SemaDeclAttr.cpp163
1 files changed, 142 insertions, 21 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 22bff86..caa7b2f 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -221,6 +221,53 @@ static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
return true;
}
+/// \brief Check if IdxExpr is a valid argument index for a function or
+/// instance method D. May output an error.
+///
+/// \returns true if IdxExpr is a valid index.
+static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,
+ StringRef AttrName,
+ SourceLocation AttrLoc,
+ unsigned AttrArgNum,
+ const Expr *IdxExpr,
+ uint64_t &Idx)
+{
+ assert(isFunctionOrMethod(D) && hasFunctionProto(D));
+
+ // In C++ the implicit 'this' function parameter also counts.
+ // Parameters are counted from one.
+ const bool HasImplicitThisParam = isInstanceMethod(D);
+ const unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
+ const unsigned FirstIdx = 1;
+
+ llvm::APSInt IdxInt;
+ if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
+ !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
+ S.Diag(AttrLoc, diag::err_attribute_argument_n_not_int)
+ << AttrName << AttrArgNum << IdxExpr->getSourceRange();
+ return false;
+ }
+
+ Idx = IdxInt.getLimitedValue();
+ if (Idx < FirstIdx || (!isFunctionOrMethodVariadic(D) && Idx > NumArgs)) {
+ S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds)
+ << AttrName << AttrArgNum << IdxExpr->getSourceRange();
+ return false;
+ }
+ Idx--; // Convert to zero-based.
+ if (HasImplicitThisParam) {
+ if (Idx == 0) {
+ S.Diag(AttrLoc,
+ diag::err_attribute_invalid_implicit_this_argument)
+ << AttrName << IdxExpr->getSourceRange();
+ return false;
+ }
+ --Idx;
+ }
+
+ return true;
+}
+
///
/// \brief Check if passed in Decl is a field or potentially shared global var
/// \return true if the Decl is a field or potentially shared global variable
@@ -3523,25 +3570,16 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
D->addAttr(::new (S.Context) PascalAttr(Attr.getRange(), S.Context));
return;
case AttributeList::AT_Pcs: {
- Expr *Arg = Attr.getArg(0);
- StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
- if (!Str || !Str->isAscii()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "pcs" << 1;
- Attr.setInvalid();
- return;
- }
-
- StringRef StrRef = Str->getString();
PcsAttr::PCSType PCS;
- if (StrRef == "aapcs")
+ switch (CC) {
+ case CC_AAPCS:
PCS = PcsAttr::AAPCS;
- else if (StrRef == "aapcs-vfp")
+ break;
+ case CC_AAPCS_VFP:
PCS = PcsAttr::AAPCS_VFP;
- else {
- S.Diag(Attr.getLoc(), diag::err_invalid_pcs);
- Attr.setInvalid();
- return;
+ break;
+ default:
+ llvm_unreachable("unexpected calling convention in pcs attribute");
}
D->addAttr(::new (S.Context) PcsAttr(Attr.getRange(), S.Context, PCS));
@@ -3560,10 +3598,9 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
if (attr.isInvalid())
return true;
- if ((attr.getNumArgs() != 0 &&
- !(attr.getKind() == AttributeList::AT_Pcs && attr.getNumArgs() == 1)) ||
- attr.getParameterName()) {
- Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0;
+ if (attr.getNumArgs() != ReqArgs || attr.getParameterName()) {
+ Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << ReqArgs;
attr.setInvalid();
return true;
}
@@ -3594,7 +3631,10 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
CC = CC_AAPCS_VFP;
break;
}
- // FALLS THROUGH
+
+ attr.setInvalid();
+ Diag(attr.getLoc(), diag::err_invalid_pcs);
+ return true;
}
default: llvm_unreachable("unexpected attribute kind");
}
@@ -3703,6 +3743,79 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
}
}
+static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ StringRef AttrName = Attr.getName()->getName();
+ if (!Attr.getParameterName()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier)
+ << Attr.getName() << /* arg num = */ 1;
+ return;
+ }
+
+ if (Attr.getNumArgs() != 2) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << /* required args = */ 3;
+ return;
+ }
+
+ IdentifierInfo *ArgumentKind = Attr.getParameterName();
+
+ if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedFunctionOrMethod;
+ return;
+ }
+
+ uint64_t ArgumentIdx;
+ if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,
+ Attr.getLoc(), 2,
+ Attr.getArg(0), ArgumentIdx))
+ return;
+
+ uint64_t TypeTagIdx;
+ if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,
+ Attr.getLoc(), 3,
+ Attr.getArg(1), TypeTagIdx))
+ return;
+
+ bool IsPointer = (AttrName == "pointer_with_type_tag");
+ if (IsPointer) {
+ // Ensure that buffer has a pointer type.
+ QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx);
+ if (!BufferTy->isPointerType()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
+ << AttrName;
+ }
+ }
+
+ D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(Attr.getRange(),
+ S.Context,
+ ArgumentKind,
+ ArgumentIdx,
+ TypeTagIdx,
+ IsPointer));
+}
+
+static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ IdentifierInfo *PointerKind = Attr.getParameterName();
+ if (!PointerKind) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier)
+ << "type_tag_for_datatype" << 1;
+ return;
+ }
+
+ QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL);
+
+ D->addAttr(::new (S.Context) TypeTagForDatatypeAttr(
+ Attr.getRange(),
+ S.Context,
+ PointerKind,
+ MatchingCType,
+ Attr.getLayoutCompatible(),
+ Attr.getMustBeNull()));
+}
+
//===----------------------------------------------------------------------===//
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
@@ -4333,6 +4446,14 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
handleAcquiredAfterAttr(S, D, Attr);
break;
+ // Type safety attributes.
+ case AttributeList::AT_ArgumentWithTypeTag:
+ handleArgumentWithTypeTagAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_TypeTagForDatatype:
+ handleTypeTagForDatatypeAttr(S, D, Attr);
+ break;
+
default:
// Ask target about the attribute.
const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
OpenPOWER on IntegriCloud