diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp | 118 |
1 files changed, 103 insertions, 15 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index 1d04159..43790c2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -2397,6 +2397,28 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { D->addAttr(NewAttr); } +// Check for things we'd like to warn about, no errors or validation for now. +// TODO: Validation should use a backend target library that specifies +// the allowable subtarget features and cpus. We could use something like a +// TargetCodeGenInfo hook here to do validation. +void Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { + for (auto Str : {"tune=", "fpmath="}) + if (AttrStr.find(Str) != StringRef::npos) + Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Str; +} + +static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) { + StringRef Str; + SourceLocation LiteralLoc; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc)) + return; + S.checkTargetAttr(LiteralLoc, Str); + unsigned Index = Attr.getAttributeSpellingListIndex(); + TargetAttr *NewAttr = + ::new (S.Context) TargetAttr(Attr.getRange(), S.Context, Str, Index); + D->addAttr(NewAttr); +} + static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { VarDecl *VD = cast<VarDecl>(D); @@ -3132,16 +3154,22 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType()) + // Base type can also be a vector type (see PR17453). + // Distinguish between base type and base element type. + QualType OldElemTy = OldTy; + if (const VectorType *VT = OldTy->getAs<VectorType>()) + OldElemTy = VT->getElementType(); + + if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType()) S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); else if (IntegerMode) { - if (!OldTy->isIntegralOrEnumerationType()) + if (!OldElemTy->isIntegralOrEnumerationType()) S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } else if (ComplexMode) { - if (!OldTy->isComplexType()) + if (!OldElemTy->isComplexType()) S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } else { - if (!OldTy->isFloatingType()) + if (!OldElemTy->isFloatingType()) S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } @@ -3154,21 +3182,40 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - QualType NewTy; + QualType NewElemTy; if (IntegerMode) - NewTy = S.Context.getIntTypeForBitwidth(DestWidth, - OldTy->isSignedIntegerType()); + NewElemTy = S.Context.getIntTypeForBitwidth( + DestWidth, OldElemTy->isSignedIntegerType()); else - NewTy = S.Context.getRealTypeForBitwidth(DestWidth); + NewElemTy = S.Context.getRealTypeForBitwidth(DestWidth); - if (NewTy.isNull()) { + if (NewElemTy.isNull()) { S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name; return; } if (ComplexMode) { - NewTy = S.Context.getComplexType(NewTy); + NewElemTy = S.Context.getComplexType(NewElemTy); + } + + QualType NewTy = NewElemTy; + if (const VectorType *OldVT = OldTy->getAs<VectorType>()) { + // Complex machine mode does not support base vector types. + if (ComplexMode) { + S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type); + return; + } + unsigned NumElements = S.Context.getTypeSize(OldElemTy) * + OldVT->getNumElements() / + S.Context.getTypeSize(NewElemTy); + NewTy = + S.Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind()); + } + + if (NewTy.isNull()) { + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + return; } // Install the new type. @@ -3683,10 +3730,31 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, returnType = PD->getType(); else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) returnType = FD->getReturnType(); - else { + else if (auto *Param = dyn_cast<ParmVarDecl>(D)) { + returnType = Param->getType()->getPointeeType(); + if (returnType.isNull()) { + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) + << Attr.getName() << /*pointer-to-CF*/2 + << Attr.getRange(); + return; + } + } else { + AttributeDeclKind ExpectedDeclKind; + switch (Attr.getKind()) { + default: llvm_unreachable("invalid ownership attribute"); + case AttributeList::AT_NSReturnsRetained: + case AttributeList::AT_NSReturnsAutoreleased: + case AttributeList::AT_NSReturnsNotRetained: + ExpectedDeclKind = ExpectedFunctionOrMethod; + break; + + case AttributeList::AT_CFReturnsRetained: + case AttributeList::AT_CFReturnsNotRetained: + ExpectedDeclKind = ExpectedFunctionMethodOrParameter; + break; + } S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) - << Attr.getRange() << Attr.getName() - << ExpectedFunctionOrMethod; + << Attr.getRange() << Attr.getName() << ExpectedDeclKind; return; } @@ -3713,8 +3781,25 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, } if (!typeOK) { - S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) - << Attr.getRange() << Attr.getName() << isa<ObjCMethodDecl>(D) << cf; + if (isa<ParmVarDecl>(D)) { + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) + << Attr.getName() << /*pointer-to-CF*/2 + << Attr.getRange(); + } else { + // Needs to be kept in sync with warn_ns_attribute_wrong_return_type. + enum : unsigned { + Function, + Method, + Property + } SubjectKind = Function; + if (isa<ObjCMethodDecl>(D)) + SubjectKind = Method; + else if (isa<ObjCPropertyDecl>(D)) + SubjectKind = Property; + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) + << Attr.getName() << SubjectKind << cf + << Attr.getRange(); + } return; } @@ -4716,6 +4801,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Section: handleSectionAttr(S, D, Attr); break; + case AttributeList::AT_Target: + handleTargetAttr(S, D, Attr); + break; case AttributeList::AT_Unavailable: handleAttrWithMessage<UnavailableAttr>(S, D, Attr); break; |