diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 4df8687aff89..b6bd2e69629d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1001,6 +1001,84 @@ public: }; } +static void handleDiagnoseAsBuiltinAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + const auto *DeclFD = cast<FunctionDecl>(D); + + if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(DeclFD)) + if (!MethodDecl->isStatic()) { + S.Diag(AL.getLoc(), diag::err_attribute_no_member_function) << AL; + return; + } + + auto DiagnoseType = [&](unsigned Index, AttributeArgumentNType T) { + SourceLocation Loc = [&]() { + auto Union = AL.getArg(Index - 1); + if (Union.is<Expr *>()) + return Union.get<Expr *>()->getBeginLoc(); + return Union.get<IdentifierLoc *>()->Loc; + }(); + + S.Diag(Loc, diag::err_attribute_argument_n_type) << AL << Index << T; + }; + + FunctionDecl *AttrFD = [&]() -> FunctionDecl * { + if (!AL.isArgExpr(0)) + return nullptr; + auto *F = dyn_cast_or_null<DeclRefExpr>(AL.getArgAsExpr(0)); + if (!F) + return nullptr; + return dyn_cast_or_null<FunctionDecl>(F->getFoundDecl()); + }(); + + if (!AttrFD || !AttrFD->getBuiltinID(true)) { + DiagnoseType(1, AANT_ArgumentBuiltinFunction); + return; + } + + if (AttrFD->getNumParams() != AL.getNumArgs() - 1) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments_for) + << AL << AttrFD << AttrFD->getNumParams(); + return; + } + + SmallVector<unsigned, 8> Indices; + + for (unsigned I = 1; I < AL.getNumArgs(); ++I) { + if (!AL.isArgExpr(I)) { + DiagnoseType(I + 1, AANT_ArgumentIntegerConstant); + return; + } + + const Expr *IndexExpr = AL.getArgAsExpr(I); + uint32_t Index; + + if (!checkUInt32Argument(S, AL, IndexExpr, Index, I + 1, false)) + return; + + if (Index > DeclFD->getNumParams()) { + S.Diag(AL.getLoc(), diag::err_attribute_bounds_for_function) + << AL << Index << DeclFD << DeclFD->getNumParams(); + return; + } + + QualType T1 = AttrFD->getParamDecl(I - 1)->getType(); + QualType T2 = DeclFD->getParamDecl(Index - 1)->getType(); + + if (T1.getCanonicalType().getUnqualifiedType() != + T2.getCanonicalType().getUnqualifiedType()) { + S.Diag(IndexExpr->getBeginLoc(), diag::err_attribute_parameter_types) + << AL << Index << DeclFD << T2 << I << AttrFD << T1; + return; + } + + Indices.push_back(Index - 1); + } + + D->addAttr(::new (S.Context) DiagnoseAsBuiltinAttr( + S.Context, AL, AttrFD, Indices.data(), Indices.size())); +} + static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if); @@ -4502,7 +4580,7 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI, return; } bool IntegralOrAnyEnumType = (OldElemTy->isIntegralOrEnumerationType() && - !OldElemTy->isExtIntType()) || + !OldElemTy->isBitIntType()) || OldElemTy->getAs<EnumType>(); if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() && @@ -8159,6 +8237,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_DiagnoseIf: handleDiagnoseIfAttr(S, D, AL); break; + case ParsedAttr::AT_DiagnoseAsBuiltin: + handleDiagnoseAsBuiltinAttr(S, D, AL); + break; case ParsedAttr::AT_NoBuiltin: handleNoBuiltinAttr(S, D, AL); break; |