10b57cec5SDimitry Andric //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements decl-related attribute processing. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h" 140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 150b57cec5SDimitry Andric #include "clang/AST/ASTMutationListener.h" 160b57cec5SDimitry Andric #include "clang/AST/CXXInheritance.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 180b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 190b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 200b57cec5SDimitry Andric #include "clang/AST/Expr.h" 210b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 220b57cec5SDimitry Andric #include "clang/AST/Mangle.h" 230b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 24e8d8bef9SDimitry Andric #include "clang/AST/Type.h" 250b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 265f757f3fSDimitry Andric #include "clang/Basic/Cuda.h" 27fe6060f1SDimitry Andric #include "clang/Basic/DarwinSDKInfo.h" 28bdd1243dSDimitry Andric #include "clang/Basic/HLSLRuntime.h" 290fca6ea1SDimitry Andric #include "clang/Basic/IdentifierTable.h" 3081ad6265SDimitry Andric #include "clang/Basic/LangOptions.h" 31e8d8bef9SDimitry Andric #include "clang/Basic/SourceLocation.h" 320b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 33480093f4SDimitry Andric #include "clang/Basic/TargetBuiltins.h" 340b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 350b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 360fca6ea1SDimitry Andric #include "clang/Sema/Attr.h" 370b57cec5SDimitry Andric #include "clang/Sema/DeclSpec.h" 380b57cec5SDimitry Andric #include "clang/Sema/DelayedDiagnostic.h" 390b57cec5SDimitry Andric #include "clang/Sema/Initialization.h" 400b57cec5SDimitry Andric #include "clang/Sema/Lookup.h" 41e8d8bef9SDimitry Andric #include "clang/Sema/ParsedAttr.h" 420b57cec5SDimitry Andric #include "clang/Sema/Scope.h" 430b57cec5SDimitry Andric #include "clang/Sema/ScopeInfo.h" 440fca6ea1SDimitry Andric #include "clang/Sema/SemaAMDGPU.h" 450fca6ea1SDimitry Andric #include "clang/Sema/SemaARM.h" 460fca6ea1SDimitry Andric #include "clang/Sema/SemaAVR.h" 470fca6ea1SDimitry Andric #include "clang/Sema/SemaBPF.h" 480fca6ea1SDimitry Andric #include "clang/Sema/SemaCUDA.h" 490fca6ea1SDimitry Andric #include "clang/Sema/SemaHLSL.h" 500b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h" 510fca6ea1SDimitry Andric #include "clang/Sema/SemaM68k.h" 520fca6ea1SDimitry Andric #include "clang/Sema/SemaMIPS.h" 530fca6ea1SDimitry Andric #include "clang/Sema/SemaMSP430.h" 540fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h" 550fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenCL.h" 560fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenMP.h" 570fca6ea1SDimitry Andric #include "clang/Sema/SemaRISCV.h" 580fca6ea1SDimitry Andric #include "clang/Sema/SemaSYCL.h" 590fca6ea1SDimitry Andric #include "clang/Sema/SemaSwift.h" 600fca6ea1SDimitry Andric #include "clang/Sema/SemaWasm.h" 610fca6ea1SDimitry Andric #include "clang/Sema/SemaX86.h" 620b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 630fca6ea1SDimitry Andric #include "llvm/ADT/STLForwardCompat.h" 640b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 650fca6ea1SDimitry Andric #include "llvm/Demangle/Demangle.h" 66e8d8bef9SDimitry Andric #include "llvm/IR/Assumptions.h" 67fe6060f1SDimitry Andric #include "llvm/MC/MCSectionMachO.h" 68fe6060f1SDimitry Andric #include "llvm/Support/Error.h" 690b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 70e8d8bef9SDimitry Andric #include "llvm/Support/raw_ostream.h" 710fca6ea1SDimitry Andric #include "llvm/TargetParser/Triple.h" 72bdd1243dSDimitry Andric #include <optional> 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric using namespace clang; 750b57cec5SDimitry Andric using namespace sema; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric namespace AttributeLangSupport { 780b57cec5SDimitry Andric enum LANG { 790b57cec5SDimitry Andric C, 800b57cec5SDimitry Andric Cpp, 810b57cec5SDimitry Andric ObjC 820b57cec5SDimitry Andric }; 830b57cec5SDimitry Andric } // end namespace AttributeLangSupport 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric static unsigned getNumAttributeArgs(const ParsedAttr &AL) { 860b57cec5SDimitry Andric // FIXME: Include the type in the argument list. 870b57cec5SDimitry Andric return AL.getNumArgs() + AL.hasParsedType(); 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900fca6ea1SDimitry Andric SourceLocation Sema::getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// Wrapper around checkUInt32Argument, with an extra check to be sure 930b57cec5SDimitry Andric /// that the result will fit into a regular (signed) int. All args have the same 940b57cec5SDimitry Andric /// purpose as they do in checkUInt32Argument. 950b57cec5SDimitry Andric template <typename AttrInfo> 960b57cec5SDimitry Andric static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr, 970b57cec5SDimitry Andric int &Val, unsigned Idx = UINT_MAX) { 980b57cec5SDimitry Andric uint32_t UVal; 990fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AI, Expr, UVal, Idx)) 1000b57cec5SDimitry Andric return false; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric if (UVal > (uint32_t)std::numeric_limits<int>::max()) { 1030b57cec5SDimitry Andric llvm::APSInt I(32); // for toString 1040b57cec5SDimitry Andric I = UVal; 1050b57cec5SDimitry Andric S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) 106fe6060f1SDimitry Andric << toString(I, 10, false) << 32 << /* Unsigned */ 0; 1070b57cec5SDimitry Andric return false; 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric Val = UVal; 1110b57cec5SDimitry Andric return true; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 11481ad6265SDimitry Andric bool Sema::checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, 11581ad6265SDimitry Andric const Expr *E, StringRef &Str, 11681ad6265SDimitry Andric SourceLocation *ArgLocation) { 11781ad6265SDimitry Andric const auto *Literal = dyn_cast<StringLiteral>(E->IgnoreParenCasts()); 11881ad6265SDimitry Andric if (ArgLocation) 11981ad6265SDimitry Andric *ArgLocation = E->getBeginLoc(); 12081ad6265SDimitry Andric 1215f757f3fSDimitry Andric if (!Literal || (!Literal->isUnevaluated() && !Literal->isOrdinary())) { 12281ad6265SDimitry Andric Diag(E->getBeginLoc(), diag::err_attribute_argument_type) 12381ad6265SDimitry Andric << CI << AANT_ArgumentString; 12481ad6265SDimitry Andric return false; 12581ad6265SDimitry Andric } 12681ad6265SDimitry Andric 12781ad6265SDimitry Andric Str = Literal->getString(); 12881ad6265SDimitry Andric return true; 12981ad6265SDimitry Andric } 13081ad6265SDimitry Andric 1310b57cec5SDimitry Andric bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, 1320b57cec5SDimitry Andric StringRef &Str, 1330b57cec5SDimitry Andric SourceLocation *ArgLocation) { 1340b57cec5SDimitry Andric // Look for identifiers. If we have one emit a hint to fix it to a literal. 1350b57cec5SDimitry Andric if (AL.isArgIdent(ArgNum)) { 1360b57cec5SDimitry Andric IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum); 1370b57cec5SDimitry Andric Diag(Loc->Loc, diag::err_attribute_argument_type) 1380b57cec5SDimitry Andric << AL << AANT_ArgumentString 1390b57cec5SDimitry Andric << FixItHint::CreateInsertion(Loc->Loc, "\"") 1400b57cec5SDimitry Andric << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\""); 1410b57cec5SDimitry Andric Str = Loc->Ident->getName(); 1420b57cec5SDimitry Andric if (ArgLocation) 1430b57cec5SDimitry Andric *ArgLocation = Loc->Loc; 1440b57cec5SDimitry Andric return true; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric // Now check for an actual string literal. 1480b57cec5SDimitry Andric Expr *ArgExpr = AL.getArgAsExpr(ArgNum); 1495f757f3fSDimitry Andric const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); 1505f757f3fSDimitry Andric if (ArgLocation) 1515f757f3fSDimitry Andric *ArgLocation = ArgExpr->getBeginLoc(); 1525f757f3fSDimitry Andric 1535f757f3fSDimitry Andric if (!Literal || (!Literal->isUnevaluated() && !Literal->isOrdinary())) { 1545f757f3fSDimitry Andric Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type) 1555f757f3fSDimitry Andric << AL << AANT_ArgumentString; 1565f757f3fSDimitry Andric return false; 1575f757f3fSDimitry Andric } 1585f757f3fSDimitry Andric Str = Literal->getString(); 15981ad6265SDimitry Andric return checkStringLiteralArgumentAttr(AL, ArgExpr, Str, ArgLocation); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric /// Check if the passed-in expression is of type int or bool. 1630b57cec5SDimitry Andric static bool isIntOrBool(Expr *Exp) { 1640b57cec5SDimitry Andric QualType QT = Exp->getType(); 1650b57cec5SDimitry Andric return QT->isBooleanType() || QT->isIntegerType(); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric // Check to see if the type is a smart pointer of some kind. We assume 1700b57cec5SDimitry Andric // it's a smart pointer if it defines both operator-> and operator*. 1710b57cec5SDimitry Andric static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { 1720b57cec5SDimitry Andric auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record, 1730b57cec5SDimitry Andric OverloadedOperatorKind Op) { 1740b57cec5SDimitry Andric DeclContextLookupResult Result = 1750b57cec5SDimitry Andric Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op)); 1760b57cec5SDimitry Andric return !Result.empty(); 1770b57cec5SDimitry Andric }; 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric const RecordDecl *Record = RT->getDecl(); 1800b57cec5SDimitry Andric bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star); 1810b57cec5SDimitry Andric bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow); 1820b57cec5SDimitry Andric if (foundStarOperator && foundArrowOperator) 1830b57cec5SDimitry Andric return true; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record); 1860b57cec5SDimitry Andric if (!CXXRecord) 1870b57cec5SDimitry Andric return false; 1880b57cec5SDimitry Andric 18906c3fb27SDimitry Andric for (const auto &BaseSpecifier : CXXRecord->bases()) { 1900b57cec5SDimitry Andric if (!foundStarOperator) 1910b57cec5SDimitry Andric foundStarOperator = IsOverloadedOperatorPresent( 1920b57cec5SDimitry Andric BaseSpecifier.getType()->getAsRecordDecl(), OO_Star); 1930b57cec5SDimitry Andric if (!foundArrowOperator) 1940b57cec5SDimitry Andric foundArrowOperator = IsOverloadedOperatorPresent( 1950b57cec5SDimitry Andric BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow); 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric if (foundStarOperator && foundArrowOperator) 1990b57cec5SDimitry Andric return true; 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric return false; 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric /// Check if passed in Decl is a pointer type. 2050b57cec5SDimitry Andric /// Note that this function may produce an error message. 2060b57cec5SDimitry Andric /// \return true if the Decl is a pointer type; false otherwise 2070b57cec5SDimitry Andric static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, 2080b57cec5SDimitry Andric const ParsedAttr &AL) { 2090b57cec5SDimitry Andric const auto *VD = cast<ValueDecl>(D); 2100b57cec5SDimitry Andric QualType QT = VD->getType(); 2110b57cec5SDimitry Andric if (QT->isAnyPointerType()) 2120b57cec5SDimitry Andric return true; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric if (const auto *RT = QT->getAs<RecordType>()) { 2150b57cec5SDimitry Andric // If it's an incomplete type, it could be a smart pointer; skip it. 2160b57cec5SDimitry Andric // (We don't want to force template instantiation if we can avoid it, 2170b57cec5SDimitry Andric // since that would alter the order in which templates are instantiated.) 2180b57cec5SDimitry Andric if (RT->isIncompleteType()) 2190b57cec5SDimitry Andric return true; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric if (threadSafetyCheckIsSmartPointer(S, RT)) 2220b57cec5SDimitry Andric return true; 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << AL << QT; 2260b57cec5SDimitry Andric return false; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric /// Checks that the passed in QualType either is of RecordType or points 2300b57cec5SDimitry Andric /// to RecordType. Returns the relevant RecordType, null if it does not exit. 2310b57cec5SDimitry Andric static const RecordType *getRecordType(QualType QT) { 2320b57cec5SDimitry Andric if (const auto *RT = QT->getAs<RecordType>()) 2330b57cec5SDimitry Andric return RT; 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric // Now check if we point to record type. 2360b57cec5SDimitry Andric if (const auto *PT = QT->getAs<PointerType>()) 2370b57cec5SDimitry Andric return PT->getPointeeType()->getAs<RecordType>(); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric return nullptr; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric template <typename AttrType> 2430b57cec5SDimitry Andric static bool checkRecordDeclForAttr(const RecordDecl *RD) { 2440b57cec5SDimitry Andric // Check if the record itself has the attribute. 2450b57cec5SDimitry Andric if (RD->hasAttr<AttrType>()) 2460b57cec5SDimitry Andric return true; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric // Else check if any base classes have the attribute. 2490b57cec5SDimitry Andric if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) { 250fe6060f1SDimitry Andric if (!CRD->forallBases([](const CXXRecordDecl *Base) { 251fe6060f1SDimitry Andric return !Base->hasAttr<AttrType>(); 252fe6060f1SDimitry Andric })) 2530b57cec5SDimitry Andric return true; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric return false; 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { 2590b57cec5SDimitry Andric const RecordType *RT = getRecordType(Ty); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric if (!RT) 2620b57cec5SDimitry Andric return false; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // Don't check for the capability if the class hasn't been defined yet. 2650b57cec5SDimitry Andric if (RT->isIncompleteType()) 2660b57cec5SDimitry Andric return true; 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric // Allow smart pointers to be used as capability objects. 2690b57cec5SDimitry Andric // FIXME -- Check the type that the smart pointer points to. 2700b57cec5SDimitry Andric if (threadSafetyCheckIsSmartPointer(S, RT)) 2710b57cec5SDimitry Andric return true; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl()); 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric static bool checkTypedefTypeForCapability(QualType Ty) { 2770b57cec5SDimitry Andric const auto *TD = Ty->getAs<TypedefType>(); 2780b57cec5SDimitry Andric if (!TD) 2790b57cec5SDimitry Andric return false; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric TypedefNameDecl *TN = TD->getDecl(); 2820b57cec5SDimitry Andric if (!TN) 2830b57cec5SDimitry Andric return false; 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric return TN->hasAttr<CapabilityAttr>(); 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric static bool typeHasCapability(Sema &S, QualType Ty) { 2890b57cec5SDimitry Andric if (checkTypedefTypeForCapability(Ty)) 2900b57cec5SDimitry Andric return true; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric if (checkRecordTypeForCapability(S, Ty)) 2930b57cec5SDimitry Andric return true; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric return false; 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric static bool isCapabilityExpr(Sema &S, const Expr *Ex) { 2990b57cec5SDimitry Andric // Capability expressions are simple expressions involving the boolean logic 3000b57cec5SDimitry Andric // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once 3010b57cec5SDimitry Andric // a DeclRefExpr is found, its type should be checked to determine whether it 3020b57cec5SDimitry Andric // is a capability or not. 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric if (const auto *E = dyn_cast<CastExpr>(Ex)) 3050b57cec5SDimitry Andric return isCapabilityExpr(S, E->getSubExpr()); 3060b57cec5SDimitry Andric else if (const auto *E = dyn_cast<ParenExpr>(Ex)) 3070b57cec5SDimitry Andric return isCapabilityExpr(S, E->getSubExpr()); 3080b57cec5SDimitry Andric else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) { 3090b57cec5SDimitry Andric if (E->getOpcode() == UO_LNot || E->getOpcode() == UO_AddrOf || 3100b57cec5SDimitry Andric E->getOpcode() == UO_Deref) 3110b57cec5SDimitry Andric return isCapabilityExpr(S, E->getSubExpr()); 3120b57cec5SDimitry Andric return false; 3130b57cec5SDimitry Andric } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) { 3140b57cec5SDimitry Andric if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr) 3150b57cec5SDimitry Andric return isCapabilityExpr(S, E->getLHS()) && 3160b57cec5SDimitry Andric isCapabilityExpr(S, E->getRHS()); 3170b57cec5SDimitry Andric return false; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric return typeHasCapability(S, Ex->getType()); 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric /// Checks that all attribute arguments, starting from Sidx, resolve to 3240b57cec5SDimitry Andric /// a capability object. 3250b57cec5SDimitry Andric /// \param Sidx The attribute argument index to start checking with. 3260b57cec5SDimitry Andric /// \param ParamIdxOk Whether an argument can be indexing into a function 3270b57cec5SDimitry Andric /// parameter list. 3280b57cec5SDimitry Andric static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, 3290b57cec5SDimitry Andric const ParsedAttr &AL, 3300b57cec5SDimitry Andric SmallVectorImpl<Expr *> &Args, 3310b57cec5SDimitry Andric unsigned Sidx = 0, 3320b57cec5SDimitry Andric bool ParamIdxOk = false) { 3330b57cec5SDimitry Andric if (Sidx == AL.getNumArgs()) { 3340b57cec5SDimitry Andric // If we don't have any capability arguments, the attribute implicitly 3350b57cec5SDimitry Andric // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're 3360b57cec5SDimitry Andric // a non-static method, and that the class is a (scoped) capability. 3370b57cec5SDimitry Andric const auto *MD = dyn_cast<const CXXMethodDecl>(D); 3380b57cec5SDimitry Andric if (MD && !MD->isStatic()) { 3390b57cec5SDimitry Andric const CXXRecordDecl *RD = MD->getParent(); 3400b57cec5SDimitry Andric // FIXME -- need to check this again on template instantiation 3410b57cec5SDimitry Andric if (!checkRecordDeclForAttr<CapabilityAttr>(RD) && 3420b57cec5SDimitry Andric !checkRecordDeclForAttr<ScopedLockableAttr>(RD)) 3430b57cec5SDimitry Andric S.Diag(AL.getLoc(), 3440b57cec5SDimitry Andric diag::warn_thread_attribute_not_on_capability_member) 3450b57cec5SDimitry Andric << AL << MD->getParent(); 3460b57cec5SDimitry Andric } else { 3470b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member) 3480b57cec5SDimitry Andric << AL; 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) { 3530b57cec5SDimitry Andric Expr *ArgExp = AL.getArgAsExpr(Idx); 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric if (ArgExp->isTypeDependent()) { 3560b57cec5SDimitry Andric // FIXME -- need to check this again on template instantiation 3570b57cec5SDimitry Andric Args.push_back(ArgExp); 3580b57cec5SDimitry Andric continue; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric if (const auto *StrLit = dyn_cast<StringLiteral>(ArgExp)) { 3620b57cec5SDimitry Andric if (StrLit->getLength() == 0 || 3630fca6ea1SDimitry Andric (StrLit->isOrdinary() && StrLit->getString() == "*")) { 3640b57cec5SDimitry Andric // Pass empty strings to the analyzer without warnings. 3650b57cec5SDimitry Andric // Treat "*" as the universal lock. 3660b57cec5SDimitry Andric Args.push_back(ArgExp); 3670b57cec5SDimitry Andric continue; 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric // We allow constant strings to be used as a placeholder for expressions 3710b57cec5SDimitry Andric // that are not valid C++ syntax, but warn that they are ignored. 3720b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL; 3730b57cec5SDimitry Andric Args.push_back(ArgExp); 3740b57cec5SDimitry Andric continue; 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric QualType ArgTy = ArgExp->getType(); 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric // A pointer to member expression of the form &MyClass::mu is treated 3800b57cec5SDimitry Andric // specially -- we need to look at the type of the member. 3810b57cec5SDimitry Andric if (const auto *UOp = dyn_cast<UnaryOperator>(ArgExp)) 3820b57cec5SDimitry Andric if (UOp->getOpcode() == UO_AddrOf) 3830b57cec5SDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr())) 3840b57cec5SDimitry Andric if (DRE->getDecl()->isCXXInstanceMember()) 3850b57cec5SDimitry Andric ArgTy = DRE->getDecl()->getType(); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric // First see if we can just cast to record type, or pointer to record type. 3880b57cec5SDimitry Andric const RecordType *RT = getRecordType(ArgTy); 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric // Now check if we index into a record type function param. 3910b57cec5SDimitry Andric if(!RT && ParamIdxOk) { 3920b57cec5SDimitry Andric const auto *FD = dyn_cast<FunctionDecl>(D); 3930b57cec5SDimitry Andric const auto *IL = dyn_cast<IntegerLiteral>(ArgExp); 3940b57cec5SDimitry Andric if(FD && IL) { 3950b57cec5SDimitry Andric unsigned int NumParams = FD->getNumParams(); 3960b57cec5SDimitry Andric llvm::APInt ArgValue = IL->getValue(); 3970b57cec5SDimitry Andric uint64_t ParamIdxFromOne = ArgValue.getZExtValue(); 3980b57cec5SDimitry Andric uint64_t ParamIdxFromZero = ParamIdxFromOne - 1; 3990b57cec5SDimitry Andric if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { 4000b57cec5SDimitry Andric S.Diag(AL.getLoc(), 4010b57cec5SDimitry Andric diag::err_attribute_argument_out_of_bounds_extra_info) 4020b57cec5SDimitry Andric << AL << Idx + 1 << NumParams; 4030b57cec5SDimitry Andric continue; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric // If the type does not have a capability, see if the components of the 4100b57cec5SDimitry Andric // expression have capabilities. This allows for writing C code where the 4110b57cec5SDimitry Andric // capability may be on the type, and the expression is a capability 4120b57cec5SDimitry Andric // boolean logic expression. Eg) requires_capability(A || B && !C) 4130b57cec5SDimitry Andric if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp)) 4140b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable) 4150b57cec5SDimitry Andric << AL << ArgTy; 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric Args.push_back(ArgExp); 4180b57cec5SDimitry Andric } 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4220b57cec5SDimitry Andric // Attribute Implementations 4230b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4260b57cec5SDimitry Andric if (!threadSafetyCheckIsPointer(S, D, AL)) 4270b57cec5SDimitry Andric return; 4280b57cec5SDimitry Andric 429a7dea167SDimitry Andric D->addAttr(::new (S.Context) PtGuardedVarAttr(S.Context, AL)); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, 4330b57cec5SDimitry Andric Expr *&Arg) { 4340b57cec5SDimitry Andric SmallVector<Expr *, 1> Args; 4350b57cec5SDimitry Andric // check that all arguments are lockable objects 4360b57cec5SDimitry Andric checkAttrArgsAreCapabilityObjs(S, D, AL, Args); 4370b57cec5SDimitry Andric unsigned Size = Args.size(); 4380b57cec5SDimitry Andric if (Size != 1) 4390b57cec5SDimitry Andric return false; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric Arg = Args[0]; 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric return true; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4470b57cec5SDimitry Andric Expr *Arg = nullptr; 4480b57cec5SDimitry Andric if (!checkGuardedByAttrCommon(S, D, AL, Arg)) 4490b57cec5SDimitry Andric return; 4500b57cec5SDimitry Andric 451a7dea167SDimitry Andric D->addAttr(::new (S.Context) GuardedByAttr(S.Context, AL, Arg)); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4550b57cec5SDimitry Andric Expr *Arg = nullptr; 4560b57cec5SDimitry Andric if (!checkGuardedByAttrCommon(S, D, AL, Arg)) 4570b57cec5SDimitry Andric return; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric if (!threadSafetyCheckIsPointer(S, D, AL)) 4600b57cec5SDimitry Andric return; 4610b57cec5SDimitry Andric 462a7dea167SDimitry Andric D->addAttr(::new (S.Context) PtGuardedByAttr(S.Context, AL, Arg)); 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, 4660b57cec5SDimitry Andric SmallVectorImpl<Expr *> &Args) { 467fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1)) 4680b57cec5SDimitry Andric return false; 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric // Check that this attribute only applies to lockable types. 4710b57cec5SDimitry Andric QualType QT = cast<ValueDecl>(D)->getType(); 4720b57cec5SDimitry Andric if (!QT->isDependentType() && !typeHasCapability(S, QT)) { 4730b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) << AL; 4740b57cec5SDimitry Andric return false; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric // Check that all arguments are lockable objects. 4780b57cec5SDimitry Andric checkAttrArgsAreCapabilityObjs(S, D, AL, Args); 4790b57cec5SDimitry Andric if (Args.empty()) 4800b57cec5SDimitry Andric return false; 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric return true; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4860b57cec5SDimitry Andric SmallVector<Expr *, 1> Args; 4870b57cec5SDimitry Andric if (!checkAcquireOrderAttrCommon(S, D, AL, Args)) 4880b57cec5SDimitry Andric return; 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric Expr **StartArg = &Args[0]; 491a7dea167SDimitry Andric D->addAttr(::new (S.Context) 492a7dea167SDimitry Andric AcquiredAfterAttr(S.Context, AL, StartArg, Args.size())); 4930b57cec5SDimitry Andric } 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4960b57cec5SDimitry Andric SmallVector<Expr *, 1> Args; 4970b57cec5SDimitry Andric if (!checkAcquireOrderAttrCommon(S, D, AL, Args)) 4980b57cec5SDimitry Andric return; 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric Expr **StartArg = &Args[0]; 501a7dea167SDimitry Andric D->addAttr(::new (S.Context) 502a7dea167SDimitry Andric AcquiredBeforeAttr(S.Context, AL, StartArg, Args.size())); 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, 5060b57cec5SDimitry Andric SmallVectorImpl<Expr *> &Args) { 5070b57cec5SDimitry Andric // zero or more arguments ok 5080b57cec5SDimitry Andric // check that all arguments are lockable objects 5090b57cec5SDimitry Andric checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, /*ParamIdxOk=*/true); 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric return true; 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 5150b57cec5SDimitry Andric SmallVector<Expr *, 1> Args; 5160b57cec5SDimitry Andric if (!checkLockFunAttrCommon(S, D, AL, Args)) 5170b57cec5SDimitry Andric return; 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric unsigned Size = Args.size(); 5200b57cec5SDimitry Andric Expr **StartArg = Size == 0 ? nullptr : &Args[0]; 5210b57cec5SDimitry Andric D->addAttr(::new (S.Context) 522a7dea167SDimitry Andric AssertSharedLockAttr(S.Context, AL, StartArg, Size)); 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, 5260b57cec5SDimitry Andric const ParsedAttr &AL) { 5270b57cec5SDimitry Andric SmallVector<Expr *, 1> Args; 5280b57cec5SDimitry Andric if (!checkLockFunAttrCommon(S, D, AL, Args)) 5290b57cec5SDimitry Andric return; 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric unsigned Size = Args.size(); 5320b57cec5SDimitry Andric Expr **StartArg = Size == 0 ? nullptr : &Args[0]; 533a7dea167SDimitry Andric D->addAttr(::new (S.Context) 534a7dea167SDimitry Andric AssertExclusiveLockAttr(S.Context, AL, StartArg, Size)); 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric /// Checks to be sure that the given parameter number is in bounds, and 5380b57cec5SDimitry Andric /// is an integral type. Will emit appropriate diagnostics if this returns 5390b57cec5SDimitry Andric /// false. 5400b57cec5SDimitry Andric /// 5410b57cec5SDimitry Andric /// AttrArgNo is used to actually retrieve the argument, so it's base-0. 5420b57cec5SDimitry Andric template <typename AttrInfo> 543fe6060f1SDimitry Andric static bool checkParamIsIntegerType(Sema &S, const Decl *D, const AttrInfo &AI, 544fe6060f1SDimitry Andric unsigned AttrArgNo) { 5450b57cec5SDimitry Andric assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument"); 5460b57cec5SDimitry Andric Expr *AttrArg = AI.getArgAsExpr(AttrArgNo); 5470b57cec5SDimitry Andric ParamIdx Idx; 5480fca6ea1SDimitry Andric if (!S.checkFunctionOrMethodParameterIndex(D, AI, AttrArgNo + 1, AttrArg, 5490b57cec5SDimitry Andric Idx)) 5500b57cec5SDimitry Andric return false; 5510b57cec5SDimitry Andric 552fe6060f1SDimitry Andric QualType ParamTy = getFunctionOrMethodParamType(D, Idx.getASTIndex()); 553fe6060f1SDimitry Andric if (!ParamTy->isIntegerType() && !ParamTy->isCharType()) { 5540b57cec5SDimitry Andric SourceLocation SrcLoc = AttrArg->getBeginLoc(); 5550b57cec5SDimitry Andric S.Diag(SrcLoc, diag::err_attribute_integers_only) 556fe6060f1SDimitry Andric << AI << getFunctionOrMethodParamRange(D, Idx.getASTIndex()); 5570b57cec5SDimitry Andric return false; 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric return true; 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 563fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2)) 5640b57cec5SDimitry Andric return; 5650b57cec5SDimitry Andric 5660fca6ea1SDimitry Andric assert(isFuncOrMethodForAttrSubject(D) && hasFunctionProto(D)); 567fe6060f1SDimitry Andric 568fe6060f1SDimitry Andric QualType RetTy = getFunctionOrMethodResultType(D); 569fe6060f1SDimitry Andric if (!RetTy->isPointerType()) { 5700b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL; 5710b57cec5SDimitry Andric return; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric const Expr *SizeExpr = AL.getArgAsExpr(0); 5750b57cec5SDimitry Andric int SizeArgNoVal; 5760b57cec5SDimitry Andric // Parameter indices are 1-indexed, hence Index=1 5770b57cec5SDimitry Andric if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Idx=*/1)) 5780b57cec5SDimitry Andric return; 579fe6060f1SDimitry Andric if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/0)) 5800b57cec5SDimitry Andric return; 5810b57cec5SDimitry Andric ParamIdx SizeArgNo(SizeArgNoVal, D); 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric ParamIdx NumberArgNo; 5840b57cec5SDimitry Andric if (AL.getNumArgs() == 2) { 5850b57cec5SDimitry Andric const Expr *NumberExpr = AL.getArgAsExpr(1); 5860b57cec5SDimitry Andric int Val; 5870b57cec5SDimitry Andric // Parameter indices are 1-based, hence Index=2 5880b57cec5SDimitry Andric if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Idx=*/2)) 5890b57cec5SDimitry Andric return; 590fe6060f1SDimitry Andric if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/1)) 5910b57cec5SDimitry Andric return; 5920b57cec5SDimitry Andric NumberArgNo = ParamIdx(Val, D); 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric D->addAttr(::new (S.Context) 596a7dea167SDimitry Andric AllocSizeAttr(S.Context, AL, SizeArgNo, NumberArgNo)); 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, 6000b57cec5SDimitry Andric SmallVectorImpl<Expr *> &Args) { 601fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1)) 6020b57cec5SDimitry Andric return false; 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric if (!isIntOrBool(AL.getArgAsExpr(0))) { 6050b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 6060b57cec5SDimitry Andric << AL << 1 << AANT_ArgumentIntOrBool; 6070b57cec5SDimitry Andric return false; 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric // check that all arguments are lockable objects 6110b57cec5SDimitry Andric checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 1); 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric return true; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, 6170b57cec5SDimitry Andric const ParsedAttr &AL) { 6180b57cec5SDimitry Andric SmallVector<Expr*, 2> Args; 6190b57cec5SDimitry Andric if (!checkTryLockFunAttrCommon(S, D, AL, Args)) 6200b57cec5SDimitry Andric return; 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric D->addAttr(::new (S.Context) SharedTrylockFunctionAttr( 623a7dea167SDimitry Andric S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, 6270b57cec5SDimitry Andric const ParsedAttr &AL) { 6280b57cec5SDimitry Andric SmallVector<Expr*, 2> Args; 6290b57cec5SDimitry Andric if (!checkTryLockFunAttrCommon(S, D, AL, Args)) 6300b57cec5SDimitry Andric return; 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr( 633a7dea167SDimitry Andric S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 6370b57cec5SDimitry Andric // check that the argument is lockable object 6380b57cec5SDimitry Andric SmallVector<Expr*, 1> Args; 6390b57cec5SDimitry Andric checkAttrArgsAreCapabilityObjs(S, D, AL, Args); 6400b57cec5SDimitry Andric unsigned Size = Args.size(); 6410b57cec5SDimitry Andric if (Size == 0) 6420b57cec5SDimitry Andric return; 6430b57cec5SDimitry Andric 644a7dea167SDimitry Andric D->addAttr(::new (S.Context) LockReturnedAttr(S.Context, AL, Args[0])); 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 648fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1)) 6490b57cec5SDimitry Andric return; 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric // check that all arguments are lockable objects 6520b57cec5SDimitry Andric SmallVector<Expr*, 1> Args; 6530b57cec5SDimitry Andric checkAttrArgsAreCapabilityObjs(S, D, AL, Args); 6540b57cec5SDimitry Andric unsigned Size = Args.size(); 6550b57cec5SDimitry Andric if (Size == 0) 6560b57cec5SDimitry Andric return; 6570b57cec5SDimitry Andric Expr **StartArg = &Args[0]; 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric D->addAttr(::new (S.Context) 660a7dea167SDimitry Andric LocksExcludedAttr(S.Context, AL, StartArg, Size)); 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL, 6640b57cec5SDimitry Andric Expr *&Cond, StringRef &Msg) { 6650b57cec5SDimitry Andric Cond = AL.getArgAsExpr(0); 6660b57cec5SDimitry Andric if (!Cond->isTypeDependent()) { 6670b57cec5SDimitry Andric ExprResult Converted = S.PerformContextuallyConvertToBool(Cond); 6680b57cec5SDimitry Andric if (Converted.isInvalid()) 6690b57cec5SDimitry Andric return false; 6700b57cec5SDimitry Andric Cond = Converted.get(); 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 1, Msg)) 6740b57cec5SDimitry Andric return false; 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric if (Msg.empty()) 6770b57cec5SDimitry Andric Msg = "<no message provided>"; 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric SmallVector<PartialDiagnosticAt, 8> Diags; 6800b57cec5SDimitry Andric if (isa<FunctionDecl>(D) && !Cond->isValueDependent() && 6810b57cec5SDimitry Andric !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D), 6820b57cec5SDimitry Andric Diags)) { 6830b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) << AL; 6840b57cec5SDimitry Andric for (const PartialDiagnosticAt &PDiag : Diags) 6850b57cec5SDimitry Andric S.Diag(PDiag.first, PDiag.second); 6860b57cec5SDimitry Andric return false; 6870b57cec5SDimitry Andric } 6880b57cec5SDimitry Andric return true; 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 6920b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::ext_clang_enable_if); 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric Expr *Cond; 6950b57cec5SDimitry Andric StringRef Msg; 6960b57cec5SDimitry Andric if (checkFunctionConditionAttr(S, D, AL, Cond, Msg)) 697a7dea167SDimitry Andric D->addAttr(::new (S.Context) EnableIfAttr(S.Context, AL, Cond, Msg)); 6980b57cec5SDimitry Andric } 6990b57cec5SDimitry Andric 700349cc55cSDimitry Andric static void handleErrorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 701349cc55cSDimitry Andric StringRef NewUserDiagnostic; 702349cc55cSDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, NewUserDiagnostic)) 703349cc55cSDimitry Andric return; 704349cc55cSDimitry Andric if (ErrorAttr *EA = S.mergeErrorAttr(D, AL, NewUserDiagnostic)) 705349cc55cSDimitry Andric D->addAttr(EA); 706349cc55cSDimitry Andric } 707349cc55cSDimitry Andric 7080fca6ea1SDimitry Andric static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D, 7090fca6ea1SDimitry Andric const ParsedAttr &AL) { 7100fca6ea1SDimitry Andric const auto *PD = isa<CXXRecordDecl>(D) 7110fca6ea1SDimitry Andric ? cast<DeclContext>(D) 7120fca6ea1SDimitry Andric : D->getDeclContext()->getRedeclContext(); 7130fca6ea1SDimitry Andric if (const auto *RD = dyn_cast<CXXRecordDecl>(PD); RD && RD->isLocalClass()) { 7140fca6ea1SDimitry Andric S.Diag(AL.getLoc(), 7150fca6ea1SDimitry Andric diag::warn_attribute_exclude_from_explicit_instantiation_local_class) 7160fca6ea1SDimitry Andric << AL << /*IsMember=*/!isa<CXXRecordDecl>(D); 7170fca6ea1SDimitry Andric return; 7180fca6ea1SDimitry Andric } 7190fca6ea1SDimitry Andric D->addAttr(::new (S.Context) 7200fca6ea1SDimitry Andric ExcludeFromExplicitInstantiationAttr(S.Context, AL)); 7210fca6ea1SDimitry Andric } 7220fca6ea1SDimitry Andric 7230b57cec5SDimitry Andric namespace { 7240b57cec5SDimitry Andric /// Determines if a given Expr references any of the given function's 7250b57cec5SDimitry Andric /// ParmVarDecls, or the function's implicit `this` parameter (if applicable). 7260b57cec5SDimitry Andric class ArgumentDependenceChecker 7270b57cec5SDimitry Andric : public RecursiveASTVisitor<ArgumentDependenceChecker> { 7280b57cec5SDimitry Andric #ifndef NDEBUG 7290b57cec5SDimitry Andric const CXXRecordDecl *ClassType; 7300b57cec5SDimitry Andric #endif 7310b57cec5SDimitry Andric llvm::SmallPtrSet<const ParmVarDecl *, 16> Parms; 7320b57cec5SDimitry Andric bool Result; 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric public: 7350b57cec5SDimitry Andric ArgumentDependenceChecker(const FunctionDecl *FD) { 7360b57cec5SDimitry Andric #ifndef NDEBUG 7370b57cec5SDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) 7380b57cec5SDimitry Andric ClassType = MD->getParent(); 7390b57cec5SDimitry Andric else 7400b57cec5SDimitry Andric ClassType = nullptr; 7410b57cec5SDimitry Andric #endif 7420b57cec5SDimitry Andric Parms.insert(FD->param_begin(), FD->param_end()); 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric bool referencesArgs(Expr *E) { 7460b57cec5SDimitry Andric Result = false; 7470b57cec5SDimitry Andric TraverseStmt(E); 7480b57cec5SDimitry Andric return Result; 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric bool VisitCXXThisExpr(CXXThisExpr *E) { 7520b57cec5SDimitry Andric assert(E->getType()->getPointeeCXXRecordDecl() == ClassType && 7530b57cec5SDimitry Andric "`this` doesn't refer to the enclosing class?"); 7540b57cec5SDimitry Andric Result = true; 7550b57cec5SDimitry Andric return false; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric bool VisitDeclRefExpr(DeclRefExpr *DRE) { 7590b57cec5SDimitry Andric if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) 7600b57cec5SDimitry Andric if (Parms.count(PVD)) { 7610b57cec5SDimitry Andric Result = true; 7620b57cec5SDimitry Andric return false; 7630b57cec5SDimitry Andric } 7640b57cec5SDimitry Andric return true; 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric }; 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric 7690eae32dcSDimitry Andric static void handleDiagnoseAsBuiltinAttr(Sema &S, Decl *D, 7700eae32dcSDimitry Andric const ParsedAttr &AL) { 7710eae32dcSDimitry Andric const auto *DeclFD = cast<FunctionDecl>(D); 7720eae32dcSDimitry Andric 7730eae32dcSDimitry Andric if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(DeclFD)) 7740eae32dcSDimitry Andric if (!MethodDecl->isStatic()) { 7750eae32dcSDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_no_member_function) << AL; 7760eae32dcSDimitry Andric return; 7770eae32dcSDimitry Andric } 7780eae32dcSDimitry Andric 7790eae32dcSDimitry Andric auto DiagnoseType = [&](unsigned Index, AttributeArgumentNType T) { 7800eae32dcSDimitry Andric SourceLocation Loc = [&]() { 7810eae32dcSDimitry Andric auto Union = AL.getArg(Index - 1); 7820eae32dcSDimitry Andric if (Union.is<Expr *>()) 7830eae32dcSDimitry Andric return Union.get<Expr *>()->getBeginLoc(); 7840eae32dcSDimitry Andric return Union.get<IdentifierLoc *>()->Loc; 7850eae32dcSDimitry Andric }(); 7860eae32dcSDimitry Andric 7870eae32dcSDimitry Andric S.Diag(Loc, diag::err_attribute_argument_n_type) << AL << Index << T; 7880eae32dcSDimitry Andric }; 7890eae32dcSDimitry Andric 7900eae32dcSDimitry Andric FunctionDecl *AttrFD = [&]() -> FunctionDecl * { 7910eae32dcSDimitry Andric if (!AL.isArgExpr(0)) 7920eae32dcSDimitry Andric return nullptr; 7935f757f3fSDimitry Andric auto *F = dyn_cast_if_present<DeclRefExpr>(AL.getArgAsExpr(0)); 7940eae32dcSDimitry Andric if (!F) 7950eae32dcSDimitry Andric return nullptr; 7965f757f3fSDimitry Andric return dyn_cast_if_present<FunctionDecl>(F->getFoundDecl()); 7970eae32dcSDimitry Andric }(); 7980eae32dcSDimitry Andric 7990eae32dcSDimitry Andric if (!AttrFD || !AttrFD->getBuiltinID(true)) { 8000eae32dcSDimitry Andric DiagnoseType(1, AANT_ArgumentBuiltinFunction); 8010eae32dcSDimitry Andric return; 8020eae32dcSDimitry Andric } 8030eae32dcSDimitry Andric 8040eae32dcSDimitry Andric if (AttrFD->getNumParams() != AL.getNumArgs() - 1) { 8050eae32dcSDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments_for) 8060eae32dcSDimitry Andric << AL << AttrFD << AttrFD->getNumParams(); 8070eae32dcSDimitry Andric return; 8080eae32dcSDimitry Andric } 8090eae32dcSDimitry Andric 8100eae32dcSDimitry Andric SmallVector<unsigned, 8> Indices; 8110eae32dcSDimitry Andric 8120eae32dcSDimitry Andric for (unsigned I = 1; I < AL.getNumArgs(); ++I) { 8130eae32dcSDimitry Andric if (!AL.isArgExpr(I)) { 8140eae32dcSDimitry Andric DiagnoseType(I + 1, AANT_ArgumentIntegerConstant); 8150eae32dcSDimitry Andric return; 8160eae32dcSDimitry Andric } 8170eae32dcSDimitry Andric 8180eae32dcSDimitry Andric const Expr *IndexExpr = AL.getArgAsExpr(I); 8190eae32dcSDimitry Andric uint32_t Index; 8200eae32dcSDimitry Andric 8210fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, IndexExpr, Index, I + 1, false)) 8220eae32dcSDimitry Andric return; 8230eae32dcSDimitry Andric 8240eae32dcSDimitry Andric if (Index > DeclFD->getNumParams()) { 8250eae32dcSDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_bounds_for_function) 8260eae32dcSDimitry Andric << AL << Index << DeclFD << DeclFD->getNumParams(); 8270eae32dcSDimitry Andric return; 8280eae32dcSDimitry Andric } 8290eae32dcSDimitry Andric 8300eae32dcSDimitry Andric QualType T1 = AttrFD->getParamDecl(I - 1)->getType(); 8310eae32dcSDimitry Andric QualType T2 = DeclFD->getParamDecl(Index - 1)->getType(); 8320eae32dcSDimitry Andric 8330eae32dcSDimitry Andric if (T1.getCanonicalType().getUnqualifiedType() != 8340eae32dcSDimitry Andric T2.getCanonicalType().getUnqualifiedType()) { 8350eae32dcSDimitry Andric S.Diag(IndexExpr->getBeginLoc(), diag::err_attribute_parameter_types) 8360eae32dcSDimitry Andric << AL << Index << DeclFD << T2 << I << AttrFD << T1; 8370eae32dcSDimitry Andric return; 8380eae32dcSDimitry Andric } 8390eae32dcSDimitry Andric 8400eae32dcSDimitry Andric Indices.push_back(Index - 1); 8410eae32dcSDimitry Andric } 8420eae32dcSDimitry Andric 8430eae32dcSDimitry Andric D->addAttr(::new (S.Context) DiagnoseAsBuiltinAttr( 8440eae32dcSDimitry Andric S.Context, AL, AttrFD, Indices.data(), Indices.size())); 8450eae32dcSDimitry Andric } 8460eae32dcSDimitry Andric 8470b57cec5SDimitry Andric static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 8480b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if); 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric Expr *Cond; 8510b57cec5SDimitry Andric StringRef Msg; 8520b57cec5SDimitry Andric if (!checkFunctionConditionAttr(S, D, AL, Cond, Msg)) 8530b57cec5SDimitry Andric return; 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric StringRef DiagTypeStr; 8560b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 2, DiagTypeStr)) 8570b57cec5SDimitry Andric return; 8580b57cec5SDimitry Andric 8590b57cec5SDimitry Andric DiagnoseIfAttr::DiagnosticType DiagType; 8600b57cec5SDimitry Andric if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) { 8610b57cec5SDimitry Andric S.Diag(AL.getArgAsExpr(2)->getBeginLoc(), 8620b57cec5SDimitry Andric diag::err_diagnose_if_invalid_diagnostic_type); 8630b57cec5SDimitry Andric return; 8640b57cec5SDimitry Andric } 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric bool ArgDependent = false; 8670b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) 8680b57cec5SDimitry Andric ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond); 8690b57cec5SDimitry Andric D->addAttr(::new (S.Context) DiagnoseIfAttr( 870a7dea167SDimitry Andric S.Context, AL, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D))); 8710b57cec5SDimitry Andric } 8720b57cec5SDimitry Andric 873480093f4SDimitry Andric static void handleNoBuiltinAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 874480093f4SDimitry Andric static constexpr const StringRef kWildcard = "*"; 875480093f4SDimitry Andric 876480093f4SDimitry Andric llvm::SmallVector<StringRef, 16> Names; 877480093f4SDimitry Andric bool HasWildcard = false; 878480093f4SDimitry Andric 879480093f4SDimitry Andric const auto AddBuiltinName = [&Names, &HasWildcard](StringRef Name) { 880480093f4SDimitry Andric if (Name == kWildcard) 881480093f4SDimitry Andric HasWildcard = true; 882480093f4SDimitry Andric Names.push_back(Name); 883480093f4SDimitry Andric }; 884480093f4SDimitry Andric 885480093f4SDimitry Andric // Add previously defined attributes. 886480093f4SDimitry Andric if (const auto *NBA = D->getAttr<NoBuiltinAttr>()) 887480093f4SDimitry Andric for (StringRef BuiltinName : NBA->builtinNames()) 888480093f4SDimitry Andric AddBuiltinName(BuiltinName); 889480093f4SDimitry Andric 890480093f4SDimitry Andric // Add current attributes. 891480093f4SDimitry Andric if (AL.getNumArgs() == 0) 892480093f4SDimitry Andric AddBuiltinName(kWildcard); 893480093f4SDimitry Andric else 894480093f4SDimitry Andric for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { 895480093f4SDimitry Andric StringRef BuiltinName; 896480093f4SDimitry Andric SourceLocation LiteralLoc; 897480093f4SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, &LiteralLoc)) 898480093f4SDimitry Andric return; 899480093f4SDimitry Andric 900480093f4SDimitry Andric if (Builtin::Context::isBuiltinFunc(BuiltinName)) 901480093f4SDimitry Andric AddBuiltinName(BuiltinName); 902480093f4SDimitry Andric else 903480093f4SDimitry Andric S.Diag(LiteralLoc, diag::warn_attribute_no_builtin_invalid_builtin_name) 9045ffd83dbSDimitry Andric << BuiltinName << AL; 905480093f4SDimitry Andric } 906480093f4SDimitry Andric 907480093f4SDimitry Andric // Repeating the same attribute is fine. 908480093f4SDimitry Andric llvm::sort(Names); 909480093f4SDimitry Andric Names.erase(std::unique(Names.begin(), Names.end()), Names.end()); 910480093f4SDimitry Andric 911480093f4SDimitry Andric // Empty no_builtin must be on its own. 912480093f4SDimitry Andric if (HasWildcard && Names.size() > 1) 913480093f4SDimitry Andric S.Diag(D->getLocation(), 914480093f4SDimitry Andric diag::err_attribute_no_builtin_wildcard_or_builtin_name) 9155ffd83dbSDimitry Andric << AL; 916480093f4SDimitry Andric 917480093f4SDimitry Andric if (D->hasAttr<NoBuiltinAttr>()) 918480093f4SDimitry Andric D->dropAttr<NoBuiltinAttr>(); 919480093f4SDimitry Andric D->addAttr(::new (S.Context) 920480093f4SDimitry Andric NoBuiltinAttr(S.Context, AL, Names.data(), Names.size())); 921480093f4SDimitry Andric } 922480093f4SDimitry Andric 9230b57cec5SDimitry Andric static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 9240b57cec5SDimitry Andric if (D->hasAttr<PassObjectSizeAttr>()) { 9250b57cec5SDimitry Andric S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL; 9260b57cec5SDimitry Andric return; 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric Expr *E = AL.getArgAsExpr(0); 9300b57cec5SDimitry Andric uint32_t Type; 9310fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, E, Type, /*Idx=*/1)) 9320b57cec5SDimitry Andric return; 9330b57cec5SDimitry Andric 9340b57cec5SDimitry Andric // pass_object_size's argument is passed in as the second argument of 9350b57cec5SDimitry Andric // __builtin_object_size. So, it has the same constraints as that second 9360b57cec5SDimitry Andric // argument; namely, it must be in the range [0, 3]. 9370b57cec5SDimitry Andric if (Type > 3) { 9380b57cec5SDimitry Andric S.Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range) 9390b57cec5SDimitry Andric << AL << 0 << 3 << E->getSourceRange(); 9400b57cec5SDimitry Andric return; 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric // pass_object_size is only supported on constant pointer parameters; as a 9440b57cec5SDimitry Andric // kindness to users, we allow the parameter to be non-const for declarations. 9450b57cec5SDimitry Andric // At this point, we have no clue if `D` belongs to a function declaration or 9460b57cec5SDimitry Andric // definition, so we defer the constness check until later. 9470b57cec5SDimitry Andric if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) { 9480b57cec5SDimitry Andric S.Diag(D->getBeginLoc(), diag::err_attribute_pointers_only) << AL << 1; 9490b57cec5SDimitry Andric return; 9500b57cec5SDimitry Andric } 9510b57cec5SDimitry Andric 952a7dea167SDimitry Andric D->addAttr(::new (S.Context) PassObjectSizeAttr(S.Context, AL, (int)Type)); 9530b57cec5SDimitry Andric } 9540b57cec5SDimitry Andric 9550b57cec5SDimitry Andric static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 9560b57cec5SDimitry Andric ConsumableAttr::ConsumedState DefaultState; 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric if (AL.isArgIdent(0)) { 9590b57cec5SDimitry Andric IdentifierLoc *IL = AL.getArgAsIdent(0); 9600b57cec5SDimitry Andric if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(), 9610b57cec5SDimitry Andric DefaultState)) { 9620b57cec5SDimitry Andric S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL 9630b57cec5SDimitry Andric << IL->Ident; 9640b57cec5SDimitry Andric return; 9650b57cec5SDimitry Andric } 9660b57cec5SDimitry Andric } else { 9670b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 9680b57cec5SDimitry Andric << AL << AANT_ArgumentIdentifier; 9690b57cec5SDimitry Andric return; 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric 972a7dea167SDimitry Andric D->addAttr(::new (S.Context) ConsumableAttr(S.Context, AL, DefaultState)); 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, 9760b57cec5SDimitry Andric const ParsedAttr &AL) { 9775f757f3fSDimitry Andric QualType ThisType = MD->getFunctionObjectParameterType(); 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { 9800b57cec5SDimitry Andric if (!RD->hasAttr<ConsumableAttr>()) { 9815ffd83dbSDimitry Andric S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) << RD; 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric return false; 9840b57cec5SDimitry Andric } 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric return true; 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 991fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1)) 9920b57cec5SDimitry Andric return; 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) 9950b57cec5SDimitry Andric return; 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric SmallVector<CallableWhenAttr::ConsumedState, 3> States; 9980b57cec5SDimitry Andric for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) { 9990b57cec5SDimitry Andric CallableWhenAttr::ConsumedState CallableState; 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric StringRef StateString; 10020b57cec5SDimitry Andric SourceLocation Loc; 10030b57cec5SDimitry Andric if (AL.isArgIdent(ArgIndex)) { 10040b57cec5SDimitry Andric IdentifierLoc *Ident = AL.getArgAsIdent(ArgIndex); 10050b57cec5SDimitry Andric StateString = Ident->Ident->getName(); 10060b57cec5SDimitry Andric Loc = Ident->Loc; 10070b57cec5SDimitry Andric } else { 10080b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, ArgIndex, StateString, &Loc)) 10090b57cec5SDimitry Andric return; 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric if (!CallableWhenAttr::ConvertStrToConsumedState(StateString, 10130b57cec5SDimitry Andric CallableState)) { 10140b57cec5SDimitry Andric S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << StateString; 10150b57cec5SDimitry Andric return; 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric States.push_back(CallableState); 10190b57cec5SDimitry Andric } 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric D->addAttr(::new (S.Context) 1022a7dea167SDimitry Andric CallableWhenAttr(S.Context, AL, States.data(), States.size())); 10230b57cec5SDimitry Andric } 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 10260b57cec5SDimitry Andric ParamTypestateAttr::ConsumedState ParamState; 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric if (AL.isArgIdent(0)) { 10290b57cec5SDimitry Andric IdentifierLoc *Ident = AL.getArgAsIdent(0); 10300b57cec5SDimitry Andric StringRef StateString = Ident->Ident->getName(); 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString, 10330b57cec5SDimitry Andric ParamState)) { 10340b57cec5SDimitry Andric S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) 10350b57cec5SDimitry Andric << AL << StateString; 10360b57cec5SDimitry Andric return; 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric } else { 10390b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 10400b57cec5SDimitry Andric << AL << AANT_ArgumentIdentifier; 10410b57cec5SDimitry Andric return; 10420b57cec5SDimitry Andric } 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric // FIXME: This check is currently being done in the analysis. It can be 10450b57cec5SDimitry Andric // enabled here only after the parser propagates attributes at 10460b57cec5SDimitry Andric // template specialization definition, not declaration. 10470b57cec5SDimitry Andric //QualType ReturnType = cast<ParmVarDecl>(D)->getType(); 10480b57cec5SDimitry Andric //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); 10490b57cec5SDimitry Andric // 10500b57cec5SDimitry Andric //if (!RD || !RD->hasAttr<ConsumableAttr>()) { 10510b57cec5SDimitry Andric // S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) << 10520b57cec5SDimitry Andric // ReturnType.getAsString(); 10530b57cec5SDimitry Andric // return; 10540b57cec5SDimitry Andric //} 10550b57cec5SDimitry Andric 1056a7dea167SDimitry Andric D->addAttr(::new (S.Context) ParamTypestateAttr(S.Context, AL, ParamState)); 10570b57cec5SDimitry Andric } 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 10600b57cec5SDimitry Andric ReturnTypestateAttr::ConsumedState ReturnState; 10610b57cec5SDimitry Andric 10620b57cec5SDimitry Andric if (AL.isArgIdent(0)) { 10630b57cec5SDimitry Andric IdentifierLoc *IL = AL.getArgAsIdent(0); 10640b57cec5SDimitry Andric if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(), 10650b57cec5SDimitry Andric ReturnState)) { 10660b57cec5SDimitry Andric S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL 10670b57cec5SDimitry Andric << IL->Ident; 10680b57cec5SDimitry Andric return; 10690b57cec5SDimitry Andric } 10700b57cec5SDimitry Andric } else { 10710b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 10720b57cec5SDimitry Andric << AL << AANT_ArgumentIdentifier; 10730b57cec5SDimitry Andric return; 10740b57cec5SDimitry Andric } 10750b57cec5SDimitry Andric 10760b57cec5SDimitry Andric // FIXME: This check is currently being done in the analysis. It can be 10770b57cec5SDimitry Andric // enabled here only after the parser propagates attributes at 10780b57cec5SDimitry Andric // template specialization definition, not declaration. 10790b57cec5SDimitry Andric // QualType ReturnType; 10800b57cec5SDimitry Andric // 10810b57cec5SDimitry Andric // if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) { 10820b57cec5SDimitry Andric // ReturnType = Param->getType(); 10830b57cec5SDimitry Andric // 10840b57cec5SDimitry Andric //} else if (const CXXConstructorDecl *Constructor = 10850b57cec5SDimitry Andric // dyn_cast<CXXConstructorDecl>(D)) { 10865f757f3fSDimitry Andric // ReturnType = Constructor->getFunctionObjectParameterType(); 10870b57cec5SDimitry Andric // 10880b57cec5SDimitry Andric //} else { 10890b57cec5SDimitry Andric // 10900b57cec5SDimitry Andric // ReturnType = cast<FunctionDecl>(D)->getCallResultType(); 10910b57cec5SDimitry Andric //} 10920b57cec5SDimitry Andric // 10930b57cec5SDimitry Andric // const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); 10940b57cec5SDimitry Andric // 10950b57cec5SDimitry Andric // if (!RD || !RD->hasAttr<ConsumableAttr>()) { 10960b57cec5SDimitry Andric // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << 10970b57cec5SDimitry Andric // ReturnType.getAsString(); 10980b57cec5SDimitry Andric // return; 10990b57cec5SDimitry Andric //} 11000b57cec5SDimitry Andric 1101a7dea167SDimitry Andric D->addAttr(::new (S.Context) ReturnTypestateAttr(S.Context, AL, ReturnState)); 11020b57cec5SDimitry Andric } 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 11050b57cec5SDimitry Andric if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) 11060b57cec5SDimitry Andric return; 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric SetTypestateAttr::ConsumedState NewState; 11090b57cec5SDimitry Andric if (AL.isArgIdent(0)) { 11100b57cec5SDimitry Andric IdentifierLoc *Ident = AL.getArgAsIdent(0); 11110b57cec5SDimitry Andric StringRef Param = Ident->Ident->getName(); 11120b57cec5SDimitry Andric if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) { 11130b57cec5SDimitry Andric S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL 11140b57cec5SDimitry Andric << Param; 11150b57cec5SDimitry Andric return; 11160b57cec5SDimitry Andric } 11170b57cec5SDimitry Andric } else { 11180b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 11190b57cec5SDimitry Andric << AL << AANT_ArgumentIdentifier; 11200b57cec5SDimitry Andric return; 11210b57cec5SDimitry Andric } 11220b57cec5SDimitry Andric 1123a7dea167SDimitry Andric D->addAttr(::new (S.Context) SetTypestateAttr(S.Context, AL, NewState)); 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 11270b57cec5SDimitry Andric if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) 11280b57cec5SDimitry Andric return; 11290b57cec5SDimitry Andric 11300b57cec5SDimitry Andric TestTypestateAttr::ConsumedState TestState; 11310b57cec5SDimitry Andric if (AL.isArgIdent(0)) { 11320b57cec5SDimitry Andric IdentifierLoc *Ident = AL.getArgAsIdent(0); 11330b57cec5SDimitry Andric StringRef Param = Ident->Ident->getName(); 11340b57cec5SDimitry Andric if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) { 11350b57cec5SDimitry Andric S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL 11360b57cec5SDimitry Andric << Param; 11370b57cec5SDimitry Andric return; 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric } else { 11400b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 11410b57cec5SDimitry Andric << AL << AANT_ArgumentIdentifier; 11420b57cec5SDimitry Andric return; 11430b57cec5SDimitry Andric } 11440b57cec5SDimitry Andric 1145a7dea167SDimitry Andric D->addAttr(::new (S.Context) TestTypestateAttr(S.Context, AL, TestState)); 11460b57cec5SDimitry Andric } 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 11490b57cec5SDimitry Andric // Remember this typedef decl, we will need it later for diagnostics. 11500b57cec5SDimitry Andric S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D)); 11510b57cec5SDimitry Andric } 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 11540b57cec5SDimitry Andric if (auto *TD = dyn_cast<TagDecl>(D)) 1155a7dea167SDimitry Andric TD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); 11560b57cec5SDimitry Andric else if (auto *FD = dyn_cast<FieldDecl>(D)) { 11570b57cec5SDimitry Andric bool BitfieldByteAligned = (!FD->getType()->isDependentType() && 11580b57cec5SDimitry Andric !FD->getType()->isIncompleteType() && 11590b57cec5SDimitry Andric FD->isBitField() && 11600b57cec5SDimitry Andric S.Context.getTypeAlign(FD->getType()) <= 8); 11610b57cec5SDimitry Andric 116281ad6265SDimitry Andric if (S.getASTContext().getTargetInfo().getTriple().isPS()) { 11630b57cec5SDimitry Andric if (BitfieldByteAligned) 116481ad6265SDimitry Andric // The PS4/PS5 targets need to maintain ABI backwards compatibility. 11650b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type) 11660b57cec5SDimitry Andric << AL << FD->getType(); 11670b57cec5SDimitry Andric else 1168a7dea167SDimitry Andric FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); 11690b57cec5SDimitry Andric } else { 11700b57cec5SDimitry Andric // Report warning about changed offset in the newer compiler versions. 11710b57cec5SDimitry Andric if (BitfieldByteAligned) 11720b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_packed_for_bitfield); 11730b57cec5SDimitry Andric 1174a7dea167SDimitry Andric FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric 11770b57cec5SDimitry Andric } else 11780b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric 1181e8d8bef9SDimitry Andric static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) { 1182e8d8bef9SDimitry Andric auto *RD = cast<CXXRecordDecl>(D); 1183e8d8bef9SDimitry Andric ClassTemplateDecl *CTD = RD->getDescribedClassTemplate(); 1184e8d8bef9SDimitry Andric assert(CTD && "attribute does not appertain to this declaration"); 1185e8d8bef9SDimitry Andric 1186e8d8bef9SDimitry Andric ParsedType PT = AL.getTypeArg(); 1187e8d8bef9SDimitry Andric TypeSourceInfo *TSI = nullptr; 1188e8d8bef9SDimitry Andric QualType T = S.GetTypeFromParser(PT, &TSI); 1189e8d8bef9SDimitry Andric if (!TSI) 1190e8d8bef9SDimitry Andric TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc()); 1191e8d8bef9SDimitry Andric 1192e8d8bef9SDimitry Andric if (!T.hasQualifiers() && T->isTypedefNameType()) { 1193e8d8bef9SDimitry Andric // Find the template name, if this type names a template specialization. 1194e8d8bef9SDimitry Andric const TemplateDecl *Template = nullptr; 11955f757f3fSDimitry Andric if (const auto *CTSD = dyn_cast_if_present<ClassTemplateSpecializationDecl>( 1196e8d8bef9SDimitry Andric T->getAsCXXRecordDecl())) { 1197e8d8bef9SDimitry Andric Template = CTSD->getSpecializedTemplate(); 1198e8d8bef9SDimitry Andric } else if (const auto *TST = T->getAs<TemplateSpecializationType>()) { 1199e8d8bef9SDimitry Andric while (TST && TST->isTypeAlias()) 1200e8d8bef9SDimitry Andric TST = TST->getAliasedType()->getAs<TemplateSpecializationType>(); 1201e8d8bef9SDimitry Andric if (TST) 1202e8d8bef9SDimitry Andric Template = TST->getTemplateName().getAsTemplateDecl(); 1203e8d8bef9SDimitry Andric } 1204e8d8bef9SDimitry Andric 1205e8d8bef9SDimitry Andric if (Template && declaresSameEntity(Template, CTD)) { 1206e8d8bef9SDimitry Andric D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI)); 1207e8d8bef9SDimitry Andric return; 1208e8d8bef9SDimitry Andric } 1209e8d8bef9SDimitry Andric } 1210e8d8bef9SDimitry Andric 1211e8d8bef9SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid) 1212e8d8bef9SDimitry Andric << T << CTD; 1213e8d8bef9SDimitry Andric if (const auto *TT = T->getAs<TypedefType>()) 1214e8d8bef9SDimitry Andric S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at) 1215e8d8bef9SDimitry Andric << TT->getDecl(); 1216e8d8bef9SDimitry Andric } 1217e8d8bef9SDimitry Andric 12180b57cec5SDimitry Andric bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) { 12190b57cec5SDimitry Andric if (RefOkay) { 12200b57cec5SDimitry Andric if (T->isReferenceType()) 12210b57cec5SDimitry Andric return true; 12220b57cec5SDimitry Andric } else { 12230b57cec5SDimitry Andric T = T.getNonReferenceType(); 12240b57cec5SDimitry Andric } 12250b57cec5SDimitry Andric 12260b57cec5SDimitry Andric // The nonnull attribute, and other similar attributes, can be applied to a 12270b57cec5SDimitry Andric // transparent union that contains a pointer type. 12280b57cec5SDimitry Andric if (const RecordType *UT = T->getAsUnionType()) { 12290b57cec5SDimitry Andric if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { 12300b57cec5SDimitry Andric RecordDecl *UD = UT->getDecl(); 12310b57cec5SDimitry Andric for (const auto *I : UD->fields()) { 12320b57cec5SDimitry Andric QualType QT = I->getType(); 12330b57cec5SDimitry Andric if (QT->isAnyPointerType() || QT->isBlockPointerType()) 12340b57cec5SDimitry Andric return true; 12350b57cec5SDimitry Andric } 12360b57cec5SDimitry Andric } 12370b57cec5SDimitry Andric } 12380b57cec5SDimitry Andric 12390b57cec5SDimitry Andric return T->isAnyPointerType() || T->isBlockPointerType(); 12400b57cec5SDimitry Andric } 12410b57cec5SDimitry Andric 12420b57cec5SDimitry Andric static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL, 12430b57cec5SDimitry Andric SourceRange AttrParmRange, 12440b57cec5SDimitry Andric SourceRange TypeRange, 12450b57cec5SDimitry Andric bool isReturnValue = false) { 12460b57cec5SDimitry Andric if (!S.isValidPointerAttrType(T)) { 12470b57cec5SDimitry Andric if (isReturnValue) 12480b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) 12490b57cec5SDimitry Andric << AL << AttrParmRange << TypeRange; 12500b57cec5SDimitry Andric else 12510b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only) 12520b57cec5SDimitry Andric << AL << AttrParmRange << TypeRange << 0; 12530b57cec5SDimitry Andric return false; 12540b57cec5SDimitry Andric } 12550b57cec5SDimitry Andric return true; 12560b57cec5SDimitry Andric } 12570b57cec5SDimitry Andric 12580b57cec5SDimitry Andric static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 12590b57cec5SDimitry Andric SmallVector<ParamIdx, 8> NonNullArgs; 12600b57cec5SDimitry Andric for (unsigned I = 0; I < AL.getNumArgs(); ++I) { 12610b57cec5SDimitry Andric Expr *Ex = AL.getArgAsExpr(I); 12620b57cec5SDimitry Andric ParamIdx Idx; 12630fca6ea1SDimitry Andric if (!S.checkFunctionOrMethodParameterIndex(D, AL, I + 1, Ex, Idx)) 12640b57cec5SDimitry Andric return; 12650b57cec5SDimitry Andric 12660b57cec5SDimitry Andric // Is the function argument a pointer type? 12670b57cec5SDimitry Andric if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) && 12680b57cec5SDimitry Andric !attrNonNullArgCheck( 12690b57cec5SDimitry Andric S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL, 12700b57cec5SDimitry Andric Ex->getSourceRange(), 12710b57cec5SDimitry Andric getFunctionOrMethodParamRange(D, Idx.getASTIndex()))) 12720b57cec5SDimitry Andric continue; 12730b57cec5SDimitry Andric 12740b57cec5SDimitry Andric NonNullArgs.push_back(Idx); 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric // If no arguments were specified to __attribute__((nonnull)) then all pointer 12780b57cec5SDimitry Andric // arguments have a nonnull attribute; warn if there aren't any. Skip this 12790b57cec5SDimitry Andric // check if the attribute came from a macro expansion or a template 12800b57cec5SDimitry Andric // instantiation. 12810b57cec5SDimitry Andric if (NonNullArgs.empty() && AL.getLoc().isFileID() && 12820b57cec5SDimitry Andric !S.inTemplateInstantiation()) { 12830b57cec5SDimitry Andric bool AnyPointers = isFunctionOrMethodVariadic(D); 12840b57cec5SDimitry Andric for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); 12850b57cec5SDimitry Andric I != E && !AnyPointers; ++I) { 12860b57cec5SDimitry Andric QualType T = getFunctionOrMethodParamType(D, I); 12870b57cec5SDimitry Andric if (T->isDependentType() || S.isValidPointerAttrType(T)) 12880b57cec5SDimitry Andric AnyPointers = true; 12890b57cec5SDimitry Andric } 12900b57cec5SDimitry Andric 12910b57cec5SDimitry Andric if (!AnyPointers) 12920b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers); 12930b57cec5SDimitry Andric } 12940b57cec5SDimitry Andric 12950b57cec5SDimitry Andric ParamIdx *Start = NonNullArgs.data(); 12960b57cec5SDimitry Andric unsigned Size = NonNullArgs.size(); 12970b57cec5SDimitry Andric llvm::array_pod_sort(Start, Start + Size); 1298a7dea167SDimitry Andric D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, Start, Size)); 12990b57cec5SDimitry Andric } 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, 13020b57cec5SDimitry Andric const ParsedAttr &AL) { 13030b57cec5SDimitry Andric if (AL.getNumArgs() > 0) { 13040b57cec5SDimitry Andric if (D->getFunctionType()) { 13050b57cec5SDimitry Andric handleNonNullAttr(S, D, AL); 13060b57cec5SDimitry Andric } else { 13070b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args) 13080b57cec5SDimitry Andric << D->getSourceRange(); 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric return; 13110b57cec5SDimitry Andric } 13120b57cec5SDimitry Andric 13130b57cec5SDimitry Andric // Is the argument a pointer type? 13140b57cec5SDimitry Andric if (!attrNonNullArgCheck(S, D->getType(), AL, SourceRange(), 13150b57cec5SDimitry Andric D->getSourceRange())) 13160b57cec5SDimitry Andric return; 13170b57cec5SDimitry Andric 1318a7dea167SDimitry Andric D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, nullptr, 0)); 13190b57cec5SDimitry Andric } 13200b57cec5SDimitry Andric 13210b57cec5SDimitry Andric static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 13220b57cec5SDimitry Andric QualType ResultType = getFunctionOrMethodResultType(D); 13230b57cec5SDimitry Andric SourceRange SR = getFunctionOrMethodResultSourceRange(D); 13240b57cec5SDimitry Andric if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR, 13250b57cec5SDimitry Andric /* isReturnValue */ true)) 13260b57cec5SDimitry Andric return; 13270b57cec5SDimitry Andric 1328a7dea167SDimitry Andric D->addAttr(::new (S.Context) ReturnsNonNullAttr(S.Context, AL)); 13290b57cec5SDimitry Andric } 13300b57cec5SDimitry Andric 13310b57cec5SDimitry Andric static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 13320b57cec5SDimitry Andric if (D->isInvalidDecl()) 13330b57cec5SDimitry Andric return; 13340b57cec5SDimitry Andric 13350b57cec5SDimitry Andric // noescape only applies to pointer types. 13360b57cec5SDimitry Andric QualType T = cast<ParmVarDecl>(D)->getType(); 13370b57cec5SDimitry Andric if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) { 13380b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only) 13390b57cec5SDimitry Andric << AL << AL.getRange() << 0; 13400b57cec5SDimitry Andric return; 13410b57cec5SDimitry Andric } 13420b57cec5SDimitry Andric 1343a7dea167SDimitry Andric D->addAttr(::new (S.Context) NoEscapeAttr(S.Context, AL)); 13440b57cec5SDimitry Andric } 13450b57cec5SDimitry Andric 13460b57cec5SDimitry Andric static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 13470b57cec5SDimitry Andric Expr *E = AL.getArgAsExpr(0), 13480b57cec5SDimitry Andric *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr; 1349a7dea167SDimitry Andric S.AddAssumeAlignedAttr(D, AL, E, OE); 13500b57cec5SDimitry Andric } 13510b57cec5SDimitry Andric 13520b57cec5SDimitry Andric static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 1353a7dea167SDimitry Andric S.AddAllocAlignAttr(D, AL, AL.getArgAsExpr(0)); 13540b57cec5SDimitry Andric } 13550b57cec5SDimitry Andric 1356a7dea167SDimitry Andric void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, 1357a7dea167SDimitry Andric Expr *OE) { 13580b57cec5SDimitry Andric QualType ResultType = getFunctionOrMethodResultType(D); 13590b57cec5SDimitry Andric SourceRange SR = getFunctionOrMethodResultSourceRange(D); 13600b57cec5SDimitry Andric 1361a7dea167SDimitry Andric AssumeAlignedAttr TmpAttr(Context, CI, E, OE); 1362a7dea167SDimitry Andric SourceLocation AttrLoc = TmpAttr.getLocation(); 13630b57cec5SDimitry Andric 13640b57cec5SDimitry Andric if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) { 13650b57cec5SDimitry Andric Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only) 1366a7dea167SDimitry Andric << &TmpAttr << TmpAttr.getRange() << SR; 13670b57cec5SDimitry Andric return; 13680b57cec5SDimitry Andric } 13690b57cec5SDimitry Andric 13700b57cec5SDimitry Andric if (!E->isValueDependent()) { 1371bdd1243dSDimitry Andric std::optional<llvm::APSInt> I = llvm::APSInt(64); 1372e8d8bef9SDimitry Andric if (!(I = E->getIntegerConstantExpr(Context))) { 13730b57cec5SDimitry Andric if (OE) 13740b57cec5SDimitry Andric Diag(AttrLoc, diag::err_attribute_argument_n_type) 13750b57cec5SDimitry Andric << &TmpAttr << 1 << AANT_ArgumentIntegerConstant 13760b57cec5SDimitry Andric << E->getSourceRange(); 13770b57cec5SDimitry Andric else 13780b57cec5SDimitry Andric Diag(AttrLoc, diag::err_attribute_argument_type) 13790b57cec5SDimitry Andric << &TmpAttr << AANT_ArgumentIntegerConstant 13800b57cec5SDimitry Andric << E->getSourceRange(); 13810b57cec5SDimitry Andric return; 13820b57cec5SDimitry Andric } 13830b57cec5SDimitry Andric 1384e8d8bef9SDimitry Andric if (!I->isPowerOf2()) { 13850b57cec5SDimitry Andric Diag(AttrLoc, diag::err_alignment_not_power_of_two) 13860b57cec5SDimitry Andric << E->getSourceRange(); 13870b57cec5SDimitry Andric return; 13880b57cec5SDimitry Andric } 13895ffd83dbSDimitry Andric 1390e8d8bef9SDimitry Andric if (*I > Sema::MaximumAlignment) 13915ffd83dbSDimitry Andric Diag(CI.getLoc(), diag::warn_assume_aligned_too_great) 13925ffd83dbSDimitry Andric << CI.getRange() << Sema::MaximumAlignment; 13930b57cec5SDimitry Andric } 13940b57cec5SDimitry Andric 1395e8d8bef9SDimitry Andric if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) { 13960b57cec5SDimitry Andric Diag(AttrLoc, diag::err_attribute_argument_n_type) 13970b57cec5SDimitry Andric << &TmpAttr << 2 << AANT_ArgumentIntegerConstant 13980b57cec5SDimitry Andric << OE->getSourceRange(); 13990b57cec5SDimitry Andric return; 14000b57cec5SDimitry Andric } 14010b57cec5SDimitry Andric 1402a7dea167SDimitry Andric D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE)); 14030b57cec5SDimitry Andric } 14040b57cec5SDimitry Andric 1405a7dea167SDimitry Andric void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI, 1406a7dea167SDimitry Andric Expr *ParamExpr) { 14070b57cec5SDimitry Andric QualType ResultType = getFunctionOrMethodResultType(D); 14080b57cec5SDimitry Andric 1409a7dea167SDimitry Andric AllocAlignAttr TmpAttr(Context, CI, ParamIdx()); 1410a7dea167SDimitry Andric SourceLocation AttrLoc = CI.getLoc(); 14110b57cec5SDimitry Andric 14120b57cec5SDimitry Andric if (!ResultType->isDependentType() && 14130b57cec5SDimitry Andric !isValidPointerAttrType(ResultType, /* RefOkay */ true)) { 14140b57cec5SDimitry Andric Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only) 1415a7dea167SDimitry Andric << &TmpAttr << CI.getRange() << getFunctionOrMethodResultSourceRange(D); 14160b57cec5SDimitry Andric return; 14170b57cec5SDimitry Andric } 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric ParamIdx Idx; 14200b57cec5SDimitry Andric const auto *FuncDecl = cast<FunctionDecl>(D); 14210fca6ea1SDimitry Andric if (!checkFunctionOrMethodParameterIndex(FuncDecl, TmpAttr, 14220b57cec5SDimitry Andric /*AttrArgNum=*/1, ParamExpr, Idx)) 14230b57cec5SDimitry Andric return; 14240b57cec5SDimitry Andric 14250b57cec5SDimitry Andric QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); 14265ffd83dbSDimitry Andric if (!Ty->isDependentType() && !Ty->isIntegralType(Context) && 14275ffd83dbSDimitry Andric !Ty->isAlignValT()) { 14280b57cec5SDimitry Andric Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only) 14290b57cec5SDimitry Andric << &TmpAttr 14300b57cec5SDimitry Andric << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange(); 14310b57cec5SDimitry Andric return; 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric 1434a7dea167SDimitry Andric D->addAttr(::new (Context) AllocAlignAttr(Context, CI, Idx)); 14350b57cec5SDimitry Andric } 14360b57cec5SDimitry Andric 14370b57cec5SDimitry Andric /// Normalize the attribute, __foo__ becomes foo. 14380b57cec5SDimitry Andric /// Returns true if normalization was applied. 14390b57cec5SDimitry Andric static bool normalizeName(StringRef &AttrName) { 14405f757f3fSDimitry Andric if (AttrName.size() > 4 && AttrName.starts_with("__") && 14415f757f3fSDimitry Andric AttrName.ends_with("__")) { 14420b57cec5SDimitry Andric AttrName = AttrName.drop_front(2).drop_back(2); 14430b57cec5SDimitry Andric return true; 14440b57cec5SDimitry Andric } 14450b57cec5SDimitry Andric return false; 14460b57cec5SDimitry Andric } 14470b57cec5SDimitry Andric 14480b57cec5SDimitry Andric static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 14490b57cec5SDimitry Andric // This attribute must be applied to a function declaration. The first 14500b57cec5SDimitry Andric // argument to the attribute must be an identifier, the name of the resource, 14510b57cec5SDimitry Andric // for example: malloc. The following arguments must be argument indexes, the 14520b57cec5SDimitry Andric // arguments must be of integer type for Returns, otherwise of pointer type. 14530b57cec5SDimitry Andric // The difference between Holds and Takes is that a pointer may still be used 14540b57cec5SDimitry Andric // after being held. free() should be __attribute((ownership_takes)), whereas 14550b57cec5SDimitry Andric // a list append function may well be __attribute((ownership_holds)). 14560b57cec5SDimitry Andric 14570b57cec5SDimitry Andric if (!AL.isArgIdent(0)) { 14580b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 14590b57cec5SDimitry Andric << AL << 1 << AANT_ArgumentIdentifier; 14600b57cec5SDimitry Andric return; 14610b57cec5SDimitry Andric } 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andric // Figure out our Kind. 14640b57cec5SDimitry Andric OwnershipAttr::OwnershipKind K = 1465a7dea167SDimitry Andric OwnershipAttr(S.Context, AL, nullptr, nullptr, 0).getOwnKind(); 14660b57cec5SDimitry Andric 14670b57cec5SDimitry Andric // Check arguments. 14680b57cec5SDimitry Andric switch (K) { 14690b57cec5SDimitry Andric case OwnershipAttr::Takes: 14700b57cec5SDimitry Andric case OwnershipAttr::Holds: 14710b57cec5SDimitry Andric if (AL.getNumArgs() < 2) { 14720b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL << 2; 14730b57cec5SDimitry Andric return; 14740b57cec5SDimitry Andric } 14750b57cec5SDimitry Andric break; 14760b57cec5SDimitry Andric case OwnershipAttr::Returns: 14770b57cec5SDimitry Andric if (AL.getNumArgs() > 2) { 14780b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; 14790b57cec5SDimitry Andric return; 14800b57cec5SDimitry Andric } 14810b57cec5SDimitry Andric break; 14820b57cec5SDimitry Andric } 14830b57cec5SDimitry Andric 14840b57cec5SDimitry Andric IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident; 14850b57cec5SDimitry Andric 14860b57cec5SDimitry Andric StringRef ModuleName = Module->getName(); 14870b57cec5SDimitry Andric if (normalizeName(ModuleName)) { 14880b57cec5SDimitry Andric Module = &S.PP.getIdentifierTable().get(ModuleName); 14890b57cec5SDimitry Andric } 14900b57cec5SDimitry Andric 14910b57cec5SDimitry Andric SmallVector<ParamIdx, 8> OwnershipArgs; 14920b57cec5SDimitry Andric for (unsigned i = 1; i < AL.getNumArgs(); ++i) { 14930b57cec5SDimitry Andric Expr *Ex = AL.getArgAsExpr(i); 14940b57cec5SDimitry Andric ParamIdx Idx; 14950fca6ea1SDimitry Andric if (!S.checkFunctionOrMethodParameterIndex(D, AL, i, Ex, Idx)) 14960b57cec5SDimitry Andric return; 14970b57cec5SDimitry Andric 14980b57cec5SDimitry Andric // Is the function argument a pointer type? 14990b57cec5SDimitry Andric QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex()); 15000b57cec5SDimitry Andric int Err = -1; // No error 15010b57cec5SDimitry Andric switch (K) { 15020b57cec5SDimitry Andric case OwnershipAttr::Takes: 15030b57cec5SDimitry Andric case OwnershipAttr::Holds: 15040b57cec5SDimitry Andric if (!T->isAnyPointerType() && !T->isBlockPointerType()) 15050b57cec5SDimitry Andric Err = 0; 15060b57cec5SDimitry Andric break; 15070b57cec5SDimitry Andric case OwnershipAttr::Returns: 15080b57cec5SDimitry Andric if (!T->isIntegerType()) 15090b57cec5SDimitry Andric Err = 1; 15100b57cec5SDimitry Andric break; 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric if (-1 != Err) { 15130b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err 15140b57cec5SDimitry Andric << Ex->getSourceRange(); 15150b57cec5SDimitry Andric return; 15160b57cec5SDimitry Andric } 15170b57cec5SDimitry Andric 15180b57cec5SDimitry Andric // Check we don't have a conflict with another ownership attribute. 15190b57cec5SDimitry Andric for (const auto *I : D->specific_attrs<OwnershipAttr>()) { 15200b57cec5SDimitry Andric // Cannot have two ownership attributes of different kinds for the same 15210b57cec5SDimitry Andric // index. 1522bdd1243dSDimitry Andric if (I->getOwnKind() != K && llvm::is_contained(I->args(), Idx)) { 152306c3fb27SDimitry Andric S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) 152406c3fb27SDimitry Andric << AL << I 152506c3fb27SDimitry Andric << (AL.isRegularKeywordAttribute() || 152606c3fb27SDimitry Andric I->isRegularKeywordAttribute()); 15270b57cec5SDimitry Andric return; 15280b57cec5SDimitry Andric } else if (K == OwnershipAttr::Returns && 15290b57cec5SDimitry Andric I->getOwnKind() == OwnershipAttr::Returns) { 15300b57cec5SDimitry Andric // A returns attribute conflicts with any other returns attribute using 15310b57cec5SDimitry Andric // a different index. 1532349cc55cSDimitry Andric if (!llvm::is_contained(I->args(), Idx)) { 15330b57cec5SDimitry Andric S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch) 15340b57cec5SDimitry Andric << I->args_begin()->getSourceIndex(); 15350b57cec5SDimitry Andric if (I->args_size()) 15360b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch) 15370b57cec5SDimitry Andric << Idx.getSourceIndex() << Ex->getSourceRange(); 15380b57cec5SDimitry Andric return; 15390b57cec5SDimitry Andric } 15400b57cec5SDimitry Andric } 15410b57cec5SDimitry Andric } 15420b57cec5SDimitry Andric OwnershipArgs.push_back(Idx); 15430b57cec5SDimitry Andric } 15440b57cec5SDimitry Andric 15450b57cec5SDimitry Andric ParamIdx *Start = OwnershipArgs.data(); 15460b57cec5SDimitry Andric unsigned Size = OwnershipArgs.size(); 15470b57cec5SDimitry Andric llvm::array_pod_sort(Start, Start + Size); 15480b57cec5SDimitry Andric D->addAttr(::new (S.Context) 1549a7dea167SDimitry Andric OwnershipAttr(S.Context, AL, Module, Start, Size)); 15500b57cec5SDimitry Andric } 15510b57cec5SDimitry Andric 15520b57cec5SDimitry Andric static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 15530b57cec5SDimitry Andric // Check the attribute arguments. 15540b57cec5SDimitry Andric if (AL.getNumArgs() > 1) { 15550b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; 15560b57cec5SDimitry Andric return; 15570b57cec5SDimitry Andric } 15580b57cec5SDimitry Andric 15590b57cec5SDimitry Andric // gcc rejects 15600b57cec5SDimitry Andric // class c { 15610b57cec5SDimitry Andric // static int a __attribute__((weakref ("v2"))); 15620b57cec5SDimitry Andric // static int b() __attribute__((weakref ("f3"))); 15630b57cec5SDimitry Andric // }; 15640b57cec5SDimitry Andric // and ignores the attributes of 15650b57cec5SDimitry Andric // void f(void) { 15660b57cec5SDimitry Andric // static int a __attribute__((weakref ("v2"))); 15670b57cec5SDimitry Andric // } 15680b57cec5SDimitry Andric // we reject them 15690b57cec5SDimitry Andric const DeclContext *Ctx = D->getDeclContext()->getRedeclContext(); 15700b57cec5SDimitry Andric if (!Ctx->isFileContext()) { 15710b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_weakref_not_global_context) 15720b57cec5SDimitry Andric << cast<NamedDecl>(D); 15730b57cec5SDimitry Andric return; 15740b57cec5SDimitry Andric } 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric // The GCC manual says 15770b57cec5SDimitry Andric // 15780b57cec5SDimitry Andric // At present, a declaration to which `weakref' is attached can only 15790b57cec5SDimitry Andric // be `static'. 15800b57cec5SDimitry Andric // 15810b57cec5SDimitry Andric // It also says 15820b57cec5SDimitry Andric // 15830b57cec5SDimitry Andric // Without a TARGET, 15840b57cec5SDimitry Andric // given as an argument to `weakref' or to `alias', `weakref' is 15850b57cec5SDimitry Andric // equivalent to `weak'. 15860b57cec5SDimitry Andric // 15870b57cec5SDimitry Andric // gcc 4.4.1 will accept 15880b57cec5SDimitry Andric // int a7 __attribute__((weakref)); 15890b57cec5SDimitry Andric // as 15900b57cec5SDimitry Andric // int a7 __attribute__((weak)); 15910b57cec5SDimitry Andric // This looks like a bug in gcc. We reject that for now. We should revisit 15920b57cec5SDimitry Andric // it if this behaviour is actually used. 15930b57cec5SDimitry Andric 15940b57cec5SDimitry Andric // GCC rejects 15950b57cec5SDimitry Andric // static ((alias ("y"), weakref)). 15960b57cec5SDimitry Andric // Should we? How to check that weakref is before or after alias? 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andric // FIXME: it would be good for us to keep the WeakRefAttr as-written instead 15990b57cec5SDimitry Andric // of transforming it into an AliasAttr. The WeakRefAttr never uses the 16000b57cec5SDimitry Andric // StringRef parameter it was given anyway. 16010b57cec5SDimitry Andric StringRef Str; 16020b57cec5SDimitry Andric if (AL.getNumArgs() && S.checkStringLiteralArgumentAttr(AL, 0, Str)) 16030b57cec5SDimitry Andric // GCC will accept anything as the argument of weakref. Should we 16040b57cec5SDimitry Andric // check for an existing decl? 1605a7dea167SDimitry Andric D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str)); 16060b57cec5SDimitry Andric 1607a7dea167SDimitry Andric D->addAttr(::new (S.Context) WeakRefAttr(S.Context, AL)); 16080b57cec5SDimitry Andric } 16090b57cec5SDimitry Andric 16100fca6ea1SDimitry Andric // Mark alias/ifunc target as used. Due to name mangling, we look up the 16110fca6ea1SDimitry Andric // demangled name ignoring parameters (not supported by microsoftDemangle 16120fca6ea1SDimitry Andric // https://github.com/llvm/llvm-project/issues/88825). This should handle the 16130fca6ea1SDimitry Andric // majority of use cases while leaving namespace scope names unmarked. 16140fca6ea1SDimitry Andric static void markUsedForAliasOrIfunc(Sema &S, Decl *D, const ParsedAttr &AL, 16150fca6ea1SDimitry Andric StringRef Str) { 16160fca6ea1SDimitry Andric std::unique_ptr<char, llvm::FreeDeleter> Demangled; 16170fca6ea1SDimitry Andric if (S.getASTContext().getCXXABIKind() != TargetCXXABI::Microsoft) 16180fca6ea1SDimitry Andric Demangled.reset(llvm::itaniumDemangle(Str, /*ParseParams=*/false)); 16190fca6ea1SDimitry Andric std::unique_ptr<MangleContext> MC(S.Context.createMangleContext()); 16200fca6ea1SDimitry Andric SmallString<256> Name; 16210fca6ea1SDimitry Andric 16220fca6ea1SDimitry Andric const DeclarationNameInfo Target( 16230fca6ea1SDimitry Andric &S.Context.Idents.get(Demangled ? Demangled.get() : Str), AL.getLoc()); 16240fca6ea1SDimitry Andric LookupResult LR(S, Target, Sema::LookupOrdinaryName); 16250fca6ea1SDimitry Andric if (S.LookupName(LR, S.TUScope)) { 16260fca6ea1SDimitry Andric for (NamedDecl *ND : LR) { 16270fca6ea1SDimitry Andric if (!isa<FunctionDecl>(ND) && !isa<VarDecl>(ND)) 16280fca6ea1SDimitry Andric continue; 16290fca6ea1SDimitry Andric if (MC->shouldMangleDeclName(ND)) { 16300fca6ea1SDimitry Andric llvm::raw_svector_ostream Out(Name); 16310fca6ea1SDimitry Andric Name.clear(); 16320fca6ea1SDimitry Andric MC->mangleName(GlobalDecl(ND), Out); 16330fca6ea1SDimitry Andric } else { 16340fca6ea1SDimitry Andric Name = ND->getIdentifier()->getName(); 16350fca6ea1SDimitry Andric } 16360fca6ea1SDimitry Andric if (Name == Str) 16370fca6ea1SDimitry Andric ND->markUsed(S.Context); 16380fca6ea1SDimitry Andric } 16390fca6ea1SDimitry Andric } 16400fca6ea1SDimitry Andric } 16410fca6ea1SDimitry Andric 16420b57cec5SDimitry Andric static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 16430b57cec5SDimitry Andric StringRef Str; 16440b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) 16450b57cec5SDimitry Andric return; 16460b57cec5SDimitry Andric 16470b57cec5SDimitry Andric // Aliases should be on declarations, not definitions. 16480b57cec5SDimitry Andric const auto *FD = cast<FunctionDecl>(D); 16490b57cec5SDimitry Andric if (FD->isThisDeclarationADefinition()) { 16500b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 1; 16510b57cec5SDimitry Andric return; 16520b57cec5SDimitry Andric } 16530b57cec5SDimitry Andric 16540fca6ea1SDimitry Andric markUsedForAliasOrIfunc(S, D, AL, Str); 1655a7dea167SDimitry Andric D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str)); 16560b57cec5SDimitry Andric } 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 16590b57cec5SDimitry Andric StringRef Str; 16600b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) 16610b57cec5SDimitry Andric return; 16620b57cec5SDimitry Andric 16630b57cec5SDimitry Andric if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { 16640b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin); 16650b57cec5SDimitry Andric return; 16660b57cec5SDimitry Andric } 16675f757f3fSDimitry Andric 16680b57cec5SDimitry Andric if (S.Context.getTargetInfo().getTriple().isNVPTX()) { 16695f757f3fSDimitry Andric CudaVersion Version = 16705f757f3fSDimitry Andric ToCudaVersion(S.Context.getTargetInfo().getSDKVersion()); 16715f757f3fSDimitry Andric if (Version != CudaVersion::UNKNOWN && Version < CudaVersion::CUDA_100) 16720b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_nvptx); 16730b57cec5SDimitry Andric } 16740b57cec5SDimitry Andric 16750b57cec5SDimitry Andric // Aliases should be on declarations, not definitions. 16760b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 16770b57cec5SDimitry Andric if (FD->isThisDeclarationADefinition()) { 16780b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 0; 16790b57cec5SDimitry Andric return; 16800b57cec5SDimitry Andric } 16810b57cec5SDimitry Andric } else { 16820b57cec5SDimitry Andric const auto *VD = cast<VarDecl>(D); 16830b57cec5SDimitry Andric if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) { 16840b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_alias_is_definition) << VD << 0; 16850b57cec5SDimitry Andric return; 16860b57cec5SDimitry Andric } 16870b57cec5SDimitry Andric } 16880b57cec5SDimitry Andric 16890fca6ea1SDimitry Andric markUsedForAliasOrIfunc(S, D, AL, Str); 1690a7dea167SDimitry Andric D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str)); 16910b57cec5SDimitry Andric } 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 16940b57cec5SDimitry Andric StringRef Model; 16950b57cec5SDimitry Andric SourceLocation LiteralLoc; 16960b57cec5SDimitry Andric // Check that it is a string. 16970b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc)) 16980b57cec5SDimitry Andric return; 16990b57cec5SDimitry Andric 17000b57cec5SDimitry Andric // Check that the value. 17010b57cec5SDimitry Andric if (Model != "global-dynamic" && Model != "local-dynamic" 17020b57cec5SDimitry Andric && Model != "initial-exec" && Model != "local-exec") { 17030b57cec5SDimitry Andric S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg); 17040b57cec5SDimitry Andric return; 17050b57cec5SDimitry Andric } 17060b57cec5SDimitry Andric 1707a7dea167SDimitry Andric D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model)); 17080b57cec5SDimitry Andric } 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 17110b57cec5SDimitry Andric QualType ResultType = getFunctionOrMethodResultType(D); 17120b57cec5SDimitry Andric if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) { 1713a7dea167SDimitry Andric D->addAttr(::new (S.Context) RestrictAttr(S.Context, AL)); 17140b57cec5SDimitry Andric return; 17150b57cec5SDimitry Andric } 17160b57cec5SDimitry Andric 17170b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) 17180b57cec5SDimitry Andric << AL << getFunctionOrMethodResultSourceRange(D); 17190b57cec5SDimitry Andric } 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 17224824e7fdSDimitry Andric // Ensure we don't combine these with themselves, since that causes some 17234824e7fdSDimitry Andric // confusing behavior. 17244824e7fdSDimitry Andric if (AL.getParsedKind() == ParsedAttr::AT_CPUDispatch) { 17254824e7fdSDimitry Andric if (checkAttrMutualExclusion<CPUSpecificAttr>(S, D, AL)) 17264824e7fdSDimitry Andric return; 17274824e7fdSDimitry Andric 17284824e7fdSDimitry Andric if (const auto *Other = D->getAttr<CPUDispatchAttr>()) { 17294824e7fdSDimitry Andric S.Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << AL; 17304824e7fdSDimitry Andric S.Diag(Other->getLocation(), diag::note_conflicting_attribute); 17314824e7fdSDimitry Andric return; 17324824e7fdSDimitry Andric } 17334824e7fdSDimitry Andric } else if (AL.getParsedKind() == ParsedAttr::AT_CPUSpecific) { 17344824e7fdSDimitry Andric if (checkAttrMutualExclusion<CPUDispatchAttr>(S, D, AL)) 17354824e7fdSDimitry Andric return; 17364824e7fdSDimitry Andric 17374824e7fdSDimitry Andric if (const auto *Other = D->getAttr<CPUSpecificAttr>()) { 17384824e7fdSDimitry Andric S.Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << AL; 17394824e7fdSDimitry Andric S.Diag(Other->getLocation(), diag::note_conflicting_attribute); 17404824e7fdSDimitry Andric return; 17414824e7fdSDimitry Andric } 17424824e7fdSDimitry Andric } 17434824e7fdSDimitry Andric 17440b57cec5SDimitry Andric FunctionDecl *FD = cast<FunctionDecl>(D); 17450b57cec5SDimitry Andric 17460b57cec5SDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { 17470b57cec5SDimitry Andric if (MD->getParent()->isLambda()) { 17480b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_dll_lambda) << AL; 17490b57cec5SDimitry Andric return; 17500b57cec5SDimitry Andric } 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric 1753fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1)) 17540b57cec5SDimitry Andric return; 17550b57cec5SDimitry Andric 17560b57cec5SDimitry Andric SmallVector<IdentifierInfo *, 8> CPUs; 17570b57cec5SDimitry Andric for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) { 17580b57cec5SDimitry Andric if (!AL.isArgIdent(ArgNo)) { 17590b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 17600b57cec5SDimitry Andric << AL << AANT_ArgumentIdentifier; 17610b57cec5SDimitry Andric return; 17620b57cec5SDimitry Andric } 17630b57cec5SDimitry Andric 17640b57cec5SDimitry Andric IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo); 17650b57cec5SDimitry Andric StringRef CPUName = CPUArg->Ident->getName().trim(); 17660b57cec5SDimitry Andric 17670b57cec5SDimitry Andric if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) { 17680b57cec5SDimitry Andric S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value) 17690b57cec5SDimitry Andric << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch); 17700b57cec5SDimitry Andric return; 17710b57cec5SDimitry Andric } 17720b57cec5SDimitry Andric 17730b57cec5SDimitry Andric const TargetInfo &Target = S.Context.getTargetInfo(); 17740b57cec5SDimitry Andric if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) { 17750b57cec5SDimitry Andric return Target.CPUSpecificManglingCharacter(CPUName) == 17760b57cec5SDimitry Andric Target.CPUSpecificManglingCharacter(Cur->getName()); 17770b57cec5SDimitry Andric })) { 17780b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries); 17790b57cec5SDimitry Andric return; 17800b57cec5SDimitry Andric } 17810b57cec5SDimitry Andric CPUs.push_back(CPUArg->Ident); 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric 17840b57cec5SDimitry Andric FD->setIsMultiVersion(true); 17850b57cec5SDimitry Andric if (AL.getKind() == ParsedAttr::AT_CPUSpecific) 1786a7dea167SDimitry Andric D->addAttr(::new (S.Context) 1787a7dea167SDimitry Andric CPUSpecificAttr(S.Context, AL, CPUs.data(), CPUs.size())); 17880b57cec5SDimitry Andric else 1789a7dea167SDimitry Andric D->addAttr(::new (S.Context) 1790a7dea167SDimitry Andric CPUDispatchAttr(S.Context, AL, CPUs.data(), CPUs.size())); 17910b57cec5SDimitry Andric } 17920b57cec5SDimitry Andric 17930b57cec5SDimitry Andric static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 17940b57cec5SDimitry Andric if (S.LangOpts.CPlusPlus) { 17950b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) 17960b57cec5SDimitry Andric << AL << AttributeLangSupport::Cpp; 17970b57cec5SDimitry Andric return; 17980b57cec5SDimitry Andric } 17990b57cec5SDimitry Andric 1800fe6060f1SDimitry Andric D->addAttr(::new (S.Context) CommonAttr(S.Context, AL)); 18010b57cec5SDimitry Andric } 18020b57cec5SDimitry Andric 18030b57cec5SDimitry Andric static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 18040b57cec5SDimitry Andric if (AL.isDeclspecAttribute()) { 18050b57cec5SDimitry Andric const auto &Triple = S.getASTContext().getTargetInfo().getTriple(); 18060b57cec5SDimitry Andric const auto &Arch = Triple.getArch(); 18070b57cec5SDimitry Andric if (Arch != llvm::Triple::x86 && 18080b57cec5SDimitry Andric (Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) { 18090b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch) 18100b57cec5SDimitry Andric << AL << Triple.getArchName(); 18110b57cec5SDimitry Andric return; 18120b57cec5SDimitry Andric } 181381ad6265SDimitry Andric 181481ad6265SDimitry Andric // This form is not allowed to be written on a member function (static or 181581ad6265SDimitry Andric // nonstatic) when in Microsoft compatibility mode. 181681ad6265SDimitry Andric if (S.getLangOpts().MSVCCompat && isa<CXXMethodDecl>(D)) { 181781ad6265SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type_str) 181806c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() << "non-member functions"; 181981ad6265SDimitry Andric return; 182081ad6265SDimitry Andric } 18210b57cec5SDimitry Andric } 18220b57cec5SDimitry Andric 1823a7dea167SDimitry Andric D->addAttr(::new (S.Context) NakedAttr(S.Context, AL)); 18240b57cec5SDimitry Andric } 18250b57cec5SDimitry Andric 18260b57cec5SDimitry Andric static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { 18270b57cec5SDimitry Andric if (hasDeclarator(D)) return; 18280b57cec5SDimitry Andric 18290b57cec5SDimitry Andric if (!isa<ObjCMethodDecl>(D)) { 18300b57cec5SDimitry Andric S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type) 183106c3fb27SDimitry Andric << Attrs << Attrs.isRegularKeywordAttribute() 183206c3fb27SDimitry Andric << ExpectedFunctionOrMethod; 18330b57cec5SDimitry Andric return; 18340b57cec5SDimitry Andric } 18350b57cec5SDimitry Andric 1836a7dea167SDimitry Andric D->addAttr(::new (S.Context) NoReturnAttr(S.Context, Attrs)); 18370b57cec5SDimitry Andric } 18380b57cec5SDimitry Andric 183981ad6265SDimitry Andric static void handleStandardNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &A) { 18405f757f3fSDimitry Andric // The [[_Noreturn]] spelling is deprecated in C23, so if that was used, 184181ad6265SDimitry Andric // issue an appropriate diagnostic. However, don't issue a diagnostic if the 184281ad6265SDimitry Andric // attribute name comes from a macro expansion. We don't want to punish users 184381ad6265SDimitry Andric // who write [[noreturn]] after including <stdnoreturn.h> (where 'noreturn' 184481ad6265SDimitry Andric // is defined as a macro which expands to '_Noreturn'). 184581ad6265SDimitry Andric if (!S.getLangOpts().CPlusPlus && 18465f757f3fSDimitry Andric A.getSemanticSpelling() == CXX11NoReturnAttr::C23_Noreturn && 184781ad6265SDimitry Andric !(A.getLoc().isMacroID() && 184881ad6265SDimitry Andric S.getSourceManager().isInSystemMacro(A.getLoc()))) 184981ad6265SDimitry Andric S.Diag(A.getLoc(), diag::warn_deprecated_noreturn_spelling) << A.getRange(); 185081ad6265SDimitry Andric 185181ad6265SDimitry Andric D->addAttr(::new (S.Context) CXX11NoReturnAttr(S.Context, A)); 185281ad6265SDimitry Andric } 185381ad6265SDimitry Andric 18540b57cec5SDimitry Andric static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { 18550b57cec5SDimitry Andric if (!S.getLangOpts().CFProtectionBranch) 18560b57cec5SDimitry Andric S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored); 18570b57cec5SDimitry Andric else 18580b57cec5SDimitry Andric handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs); 18590b57cec5SDimitry Andric } 18600b57cec5SDimitry Andric 18610b57cec5SDimitry Andric bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) { 1862fe6060f1SDimitry Andric if (!Attrs.checkExactlyNumArgs(*this, 0)) { 18630b57cec5SDimitry Andric Attrs.setInvalid(); 18640b57cec5SDimitry Andric return true; 18650b57cec5SDimitry Andric } 18660b57cec5SDimitry Andric 18670b57cec5SDimitry Andric return false; 18680b57cec5SDimitry Andric } 18690b57cec5SDimitry Andric 18700b57cec5SDimitry Andric bool Sema::CheckAttrTarget(const ParsedAttr &AL) { 18710b57cec5SDimitry Andric // Check whether the attribute is valid on the current target. 18720b57cec5SDimitry Andric if (!AL.existsInTarget(Context.getTargetInfo())) { 187306c3fb27SDimitry Andric Diag(AL.getLoc(), AL.isRegularKeywordAttribute() 187406c3fb27SDimitry Andric ? diag::err_keyword_not_supported_on_target 187506c3fb27SDimitry Andric : diag::warn_unknown_attribute_ignored) 1876e8d8bef9SDimitry Andric << AL << AL.getRange(); 18770b57cec5SDimitry Andric AL.setInvalid(); 18780b57cec5SDimitry Andric return true; 18790b57cec5SDimitry Andric } 18800b57cec5SDimitry Andric 18810b57cec5SDimitry Andric return false; 18820b57cec5SDimitry Andric } 18830b57cec5SDimitry Andric 18840b57cec5SDimitry Andric static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 18850b57cec5SDimitry Andric 18860b57cec5SDimitry Andric // The checking path for 'noreturn' and 'analyzer_noreturn' are different 18870b57cec5SDimitry Andric // because 'analyzer_noreturn' does not impact the type. 18880fca6ea1SDimitry Andric if (!isFunctionOrMethodOrBlockForAttrSubject(D)) { 18890b57cec5SDimitry Andric ValueDecl *VD = dyn_cast<ValueDecl>(D); 18900b57cec5SDimitry Andric if (!VD || (!VD->getType()->isBlockPointerType() && 18910b57cec5SDimitry Andric !VD->getType()->isFunctionPointerType())) { 1892fe6060f1SDimitry Andric S.Diag(AL.getLoc(), AL.isStandardAttributeSyntax() 18930b57cec5SDimitry Andric ? diag::err_attribute_wrong_decl_type 18940b57cec5SDimitry Andric : diag::warn_attribute_wrong_decl_type) 189506c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() 189606c3fb27SDimitry Andric << ExpectedFunctionMethodOrBlock; 18970b57cec5SDimitry Andric return; 18980b57cec5SDimitry Andric } 18990b57cec5SDimitry Andric } 19000b57cec5SDimitry Andric 1901a7dea167SDimitry Andric D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(S.Context, AL)); 19020b57cec5SDimitry Andric } 19030b57cec5SDimitry Andric 19040b57cec5SDimitry Andric // PS3 PPU-specific. 19050b57cec5SDimitry Andric static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 19060b57cec5SDimitry Andric /* 19070b57cec5SDimitry Andric Returning a Vector Class in Registers 19080b57cec5SDimitry Andric 19090b57cec5SDimitry Andric According to the PPU ABI specifications, a class with a single member of 19100b57cec5SDimitry Andric vector type is returned in memory when used as the return value of a 19110b57cec5SDimitry Andric function. 19120b57cec5SDimitry Andric This results in inefficient code when implementing vector classes. To return 19130b57cec5SDimitry Andric the value in a single vector register, add the vecreturn attribute to the 19140b57cec5SDimitry Andric class definition. This attribute is also applicable to struct types. 19150b57cec5SDimitry Andric 19160b57cec5SDimitry Andric Example: 19170b57cec5SDimitry Andric 19180b57cec5SDimitry Andric struct Vector 19190b57cec5SDimitry Andric { 19200b57cec5SDimitry Andric __vector float xyzw; 19210b57cec5SDimitry Andric } __attribute__((vecreturn)); 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric Vector Add(Vector lhs, Vector rhs) 19240b57cec5SDimitry Andric { 19250b57cec5SDimitry Andric Vector result; 19260b57cec5SDimitry Andric result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); 19270b57cec5SDimitry Andric return result; // This will be returned in a register 19280b57cec5SDimitry Andric } 19290b57cec5SDimitry Andric */ 19300b57cec5SDimitry Andric if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) { 19310b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A; 19320b57cec5SDimitry Andric return; 19330b57cec5SDimitry Andric } 19340b57cec5SDimitry Andric 19350b57cec5SDimitry Andric const auto *R = cast<RecordDecl>(D); 19360b57cec5SDimitry Andric int count = 0; 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric if (!isa<CXXRecordDecl>(R)) { 19390b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member); 19400b57cec5SDimitry Andric return; 19410b57cec5SDimitry Andric } 19420b57cec5SDimitry Andric 19430b57cec5SDimitry Andric if (!cast<CXXRecordDecl>(R)->isPOD()) { 19440b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_pod_record); 19450b57cec5SDimitry Andric return; 19460b57cec5SDimitry Andric } 19470b57cec5SDimitry Andric 19480b57cec5SDimitry Andric for (const auto *I : R->fields()) { 19490b57cec5SDimitry Andric if ((count == 1) || !I->getType()->isVectorType()) { 19500b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member); 19510b57cec5SDimitry Andric return; 19520b57cec5SDimitry Andric } 19530b57cec5SDimitry Andric count++; 19540b57cec5SDimitry Andric } 19550b57cec5SDimitry Andric 1956a7dea167SDimitry Andric D->addAttr(::new (S.Context) VecReturnAttr(S.Context, AL)); 19570b57cec5SDimitry Andric } 19580b57cec5SDimitry Andric 19590b57cec5SDimitry Andric static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, 19600b57cec5SDimitry Andric const ParsedAttr &AL) { 19610b57cec5SDimitry Andric if (isa<ParmVarDecl>(D)) { 19620b57cec5SDimitry Andric // [[carries_dependency]] can only be applied to a parameter if it is a 19630b57cec5SDimitry Andric // parameter of a function declaration or lambda. 19640b57cec5SDimitry Andric if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { 19650b57cec5SDimitry Andric S.Diag(AL.getLoc(), 19660b57cec5SDimitry Andric diag::err_carries_dependency_param_not_function_decl); 19670b57cec5SDimitry Andric return; 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric } 19700b57cec5SDimitry Andric 1971a7dea167SDimitry Andric D->addAttr(::new (S.Context) CarriesDependencyAttr(S.Context, AL)); 19720b57cec5SDimitry Andric } 19730b57cec5SDimitry Andric 19740b57cec5SDimitry Andric static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 19750b57cec5SDimitry Andric bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName(); 19760b57cec5SDimitry Andric 19770b57cec5SDimitry Andric // If this is spelled as the standard C++17 attribute, but not in C++17, warn 19780b57cec5SDimitry Andric // about using it as an extension. 19790b57cec5SDimitry Andric if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr) 19800b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; 19810b57cec5SDimitry Andric 1982a7dea167SDimitry Andric D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL)); 19830b57cec5SDimitry Andric } 19840b57cec5SDimitry Andric 19850b57cec5SDimitry Andric static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 19860b57cec5SDimitry Andric uint32_t priority = ConstructorAttr::DefaultPriority; 1987bdd1243dSDimitry Andric if (S.getLangOpts().HLSL && AL.getNumArgs()) { 1988bdd1243dSDimitry Andric S.Diag(AL.getLoc(), diag::err_hlsl_init_priority_unsupported); 1989bdd1243dSDimitry Andric return; 1990bdd1243dSDimitry Andric } 19910b57cec5SDimitry Andric if (AL.getNumArgs() && 19920fca6ea1SDimitry Andric !S.checkUInt32Argument(AL, AL.getArgAsExpr(0), priority)) 19930b57cec5SDimitry Andric return; 19940b57cec5SDimitry Andric 1995a7dea167SDimitry Andric D->addAttr(::new (S.Context) ConstructorAttr(S.Context, AL, priority)); 19960b57cec5SDimitry Andric } 19970b57cec5SDimitry Andric 19980b57cec5SDimitry Andric static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 19990b57cec5SDimitry Andric uint32_t priority = DestructorAttr::DefaultPriority; 20000b57cec5SDimitry Andric if (AL.getNumArgs() && 20010fca6ea1SDimitry Andric !S.checkUInt32Argument(AL, AL.getArgAsExpr(0), priority)) 20020b57cec5SDimitry Andric return; 20030b57cec5SDimitry Andric 2004a7dea167SDimitry Andric D->addAttr(::new (S.Context) DestructorAttr(S.Context, AL, priority)); 20050b57cec5SDimitry Andric } 20060b57cec5SDimitry Andric 20070b57cec5SDimitry Andric template <typename AttrTy> 20080b57cec5SDimitry Andric static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) { 20090b57cec5SDimitry Andric // Handle the case where the attribute has a text message. 20100b57cec5SDimitry Andric StringRef Str; 20110b57cec5SDimitry Andric if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str)) 20120b57cec5SDimitry Andric return; 20130b57cec5SDimitry Andric 2014a7dea167SDimitry Andric D->addAttr(::new (S.Context) AttrTy(S.Context, AL, Str)); 20150b57cec5SDimitry Andric } 20160b57cec5SDimitry Andric 20170b57cec5SDimitry Andric static bool checkAvailabilityAttr(Sema &S, SourceRange Range, 20180b57cec5SDimitry Andric IdentifierInfo *Platform, 20190b57cec5SDimitry Andric VersionTuple Introduced, 20200b57cec5SDimitry Andric VersionTuple Deprecated, 20210b57cec5SDimitry Andric VersionTuple Obsoleted) { 20220b57cec5SDimitry Andric StringRef PlatformName 20230b57cec5SDimitry Andric = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); 20240b57cec5SDimitry Andric if (PlatformName.empty()) 20250b57cec5SDimitry Andric PlatformName = Platform->getName(); 20260b57cec5SDimitry Andric 20270b57cec5SDimitry Andric // Ensure that Introduced <= Deprecated <= Obsoleted (although not all 20280b57cec5SDimitry Andric // of these steps are needed). 20290b57cec5SDimitry Andric if (!Introduced.empty() && !Deprecated.empty() && 20300b57cec5SDimitry Andric !(Introduced <= Deprecated)) { 20310b57cec5SDimitry Andric S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 20320b57cec5SDimitry Andric << 1 << PlatformName << Deprecated.getAsString() 20330b57cec5SDimitry Andric << 0 << Introduced.getAsString(); 20340b57cec5SDimitry Andric return true; 20350b57cec5SDimitry Andric } 20360b57cec5SDimitry Andric 20370b57cec5SDimitry Andric if (!Introduced.empty() && !Obsoleted.empty() && 20380b57cec5SDimitry Andric !(Introduced <= Obsoleted)) { 20390b57cec5SDimitry Andric S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 20400b57cec5SDimitry Andric << 2 << PlatformName << Obsoleted.getAsString() 20410b57cec5SDimitry Andric << 0 << Introduced.getAsString(); 20420b57cec5SDimitry Andric return true; 20430b57cec5SDimitry Andric } 20440b57cec5SDimitry Andric 20450b57cec5SDimitry Andric if (!Deprecated.empty() && !Obsoleted.empty() && 20460b57cec5SDimitry Andric !(Deprecated <= Obsoleted)) { 20470b57cec5SDimitry Andric S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 20480b57cec5SDimitry Andric << 2 << PlatformName << Obsoleted.getAsString() 20490b57cec5SDimitry Andric << 1 << Deprecated.getAsString(); 20500b57cec5SDimitry Andric return true; 20510b57cec5SDimitry Andric } 20520b57cec5SDimitry Andric 20530b57cec5SDimitry Andric return false; 20540b57cec5SDimitry Andric } 20550b57cec5SDimitry Andric 20560b57cec5SDimitry Andric /// Check whether the two versions match. 20570b57cec5SDimitry Andric /// 20580b57cec5SDimitry Andric /// If either version tuple is empty, then they are assumed to match. If 20590b57cec5SDimitry Andric /// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y. 20600b57cec5SDimitry Andric static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, 20610b57cec5SDimitry Andric bool BeforeIsOkay) { 20620b57cec5SDimitry Andric if (X.empty() || Y.empty()) 20630b57cec5SDimitry Andric return true; 20640b57cec5SDimitry Andric 20650b57cec5SDimitry Andric if (X == Y) 20660b57cec5SDimitry Andric return true; 20670b57cec5SDimitry Andric 20680b57cec5SDimitry Andric if (BeforeIsOkay && X < Y) 20690b57cec5SDimitry Andric return true; 20700b57cec5SDimitry Andric 20710b57cec5SDimitry Andric return false; 20720b57cec5SDimitry Andric } 20730b57cec5SDimitry Andric 20740b57cec5SDimitry Andric AvailabilityAttr *Sema::mergeAvailabilityAttr( 2075a7dea167SDimitry Andric NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform, 2076a7dea167SDimitry Andric bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, 2077a7dea167SDimitry Andric VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, 2078a7dea167SDimitry Andric bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK, 20790fca6ea1SDimitry Andric int Priority, IdentifierInfo *Environment) { 20800b57cec5SDimitry Andric VersionTuple MergedIntroduced = Introduced; 20810b57cec5SDimitry Andric VersionTuple MergedDeprecated = Deprecated; 20820b57cec5SDimitry Andric VersionTuple MergedObsoleted = Obsoleted; 20830b57cec5SDimitry Andric bool FoundAny = false; 20840b57cec5SDimitry Andric bool OverrideOrImpl = false; 20850b57cec5SDimitry Andric switch (AMK) { 20860b57cec5SDimitry Andric case AMK_None: 20870b57cec5SDimitry Andric case AMK_Redeclaration: 20880b57cec5SDimitry Andric OverrideOrImpl = false; 20890b57cec5SDimitry Andric break; 20900b57cec5SDimitry Andric 20910b57cec5SDimitry Andric case AMK_Override: 20920b57cec5SDimitry Andric case AMK_ProtocolImplementation: 2093fe6060f1SDimitry Andric case AMK_OptionalProtocolImplementation: 20940b57cec5SDimitry Andric OverrideOrImpl = true; 20950b57cec5SDimitry Andric break; 20960b57cec5SDimitry Andric } 20970b57cec5SDimitry Andric 20980b57cec5SDimitry Andric if (D->hasAttrs()) { 20990b57cec5SDimitry Andric AttrVec &Attrs = D->getAttrs(); 21000b57cec5SDimitry Andric for (unsigned i = 0, e = Attrs.size(); i != e;) { 21010b57cec5SDimitry Andric const auto *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]); 21020b57cec5SDimitry Andric if (!OldAA) { 21030b57cec5SDimitry Andric ++i; 21040b57cec5SDimitry Andric continue; 21050b57cec5SDimitry Andric } 21060b57cec5SDimitry Andric 21070b57cec5SDimitry Andric IdentifierInfo *OldPlatform = OldAA->getPlatform(); 21080b57cec5SDimitry Andric if (OldPlatform != Platform) { 21090b57cec5SDimitry Andric ++i; 21100b57cec5SDimitry Andric continue; 21110b57cec5SDimitry Andric } 21120b57cec5SDimitry Andric 21130fca6ea1SDimitry Andric IdentifierInfo *OldEnvironment = OldAA->getEnvironment(); 21140fca6ea1SDimitry Andric if (OldEnvironment != Environment) { 21150fca6ea1SDimitry Andric ++i; 21160fca6ea1SDimitry Andric continue; 21170fca6ea1SDimitry Andric } 21180fca6ea1SDimitry Andric 21190b57cec5SDimitry Andric // If there is an existing availability attribute for this platform that 21200b57cec5SDimitry Andric // has a lower priority use the existing one and discard the new 21210b57cec5SDimitry Andric // attribute. 21220b57cec5SDimitry Andric if (OldAA->getPriority() < Priority) 21230b57cec5SDimitry Andric return nullptr; 21240b57cec5SDimitry Andric 21250b57cec5SDimitry Andric // If there is an existing attribute for this platform that has a higher 21260b57cec5SDimitry Andric // priority than the new attribute then erase the old one and continue 21270b57cec5SDimitry Andric // processing the attributes. 21280b57cec5SDimitry Andric if (OldAA->getPriority() > Priority) { 21290b57cec5SDimitry Andric Attrs.erase(Attrs.begin() + i); 21300b57cec5SDimitry Andric --e; 21310b57cec5SDimitry Andric continue; 21320b57cec5SDimitry Andric } 21330b57cec5SDimitry Andric 21340b57cec5SDimitry Andric FoundAny = true; 21350b57cec5SDimitry Andric VersionTuple OldIntroduced = OldAA->getIntroduced(); 21360b57cec5SDimitry Andric VersionTuple OldDeprecated = OldAA->getDeprecated(); 21370b57cec5SDimitry Andric VersionTuple OldObsoleted = OldAA->getObsoleted(); 21380b57cec5SDimitry Andric bool OldIsUnavailable = OldAA->getUnavailable(); 21390b57cec5SDimitry Andric 21400b57cec5SDimitry Andric if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) || 21410b57cec5SDimitry Andric !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) || 21420b57cec5SDimitry Andric !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) || 21430b57cec5SDimitry Andric !(OldIsUnavailable == IsUnavailable || 21440b57cec5SDimitry Andric (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) { 21450b57cec5SDimitry Andric if (OverrideOrImpl) { 21460b57cec5SDimitry Andric int Which = -1; 21470b57cec5SDimitry Andric VersionTuple FirstVersion; 21480b57cec5SDimitry Andric VersionTuple SecondVersion; 21490b57cec5SDimitry Andric if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) { 21500b57cec5SDimitry Andric Which = 0; 21510b57cec5SDimitry Andric FirstVersion = OldIntroduced; 21520b57cec5SDimitry Andric SecondVersion = Introduced; 21530b57cec5SDimitry Andric } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) { 21540b57cec5SDimitry Andric Which = 1; 21550b57cec5SDimitry Andric FirstVersion = Deprecated; 21560b57cec5SDimitry Andric SecondVersion = OldDeprecated; 21570b57cec5SDimitry Andric } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) { 21580b57cec5SDimitry Andric Which = 2; 21590b57cec5SDimitry Andric FirstVersion = Obsoleted; 21600b57cec5SDimitry Andric SecondVersion = OldObsoleted; 21610b57cec5SDimitry Andric } 21620b57cec5SDimitry Andric 21630b57cec5SDimitry Andric if (Which == -1) { 21640b57cec5SDimitry Andric Diag(OldAA->getLocation(), 21650b57cec5SDimitry Andric diag::warn_mismatched_availability_override_unavail) 21660b57cec5SDimitry Andric << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) 21670b57cec5SDimitry Andric << (AMK == AMK_Override); 2168fe6060f1SDimitry Andric } else if (Which != 1 && AMK == AMK_OptionalProtocolImplementation) { 2169fe6060f1SDimitry Andric // Allow different 'introduced' / 'obsoleted' availability versions 2170fe6060f1SDimitry Andric // on a method that implements an optional protocol requirement. It 2171fe6060f1SDimitry Andric // makes less sense to allow this for 'deprecated' as the user can't 2172fe6060f1SDimitry Andric // see if the method is 'deprecated' as 'respondsToSelector' will 2173fe6060f1SDimitry Andric // still return true when the method is deprecated. 2174fe6060f1SDimitry Andric ++i; 2175fe6060f1SDimitry Andric continue; 21760b57cec5SDimitry Andric } else { 21770b57cec5SDimitry Andric Diag(OldAA->getLocation(), 21780b57cec5SDimitry Andric diag::warn_mismatched_availability_override) 21790b57cec5SDimitry Andric << Which 21800b57cec5SDimitry Andric << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) 21810b57cec5SDimitry Andric << FirstVersion.getAsString() << SecondVersion.getAsString() 21820b57cec5SDimitry Andric << (AMK == AMK_Override); 21830b57cec5SDimitry Andric } 21840b57cec5SDimitry Andric if (AMK == AMK_Override) 2185a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_overridden_method); 21860b57cec5SDimitry Andric else 2187a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_protocol_method); 21880b57cec5SDimitry Andric } else { 21890b57cec5SDimitry Andric Diag(OldAA->getLocation(), diag::warn_mismatched_availability); 2190a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_previous_attribute); 21910b57cec5SDimitry Andric } 21920b57cec5SDimitry Andric 21930b57cec5SDimitry Andric Attrs.erase(Attrs.begin() + i); 21940b57cec5SDimitry Andric --e; 21950b57cec5SDimitry Andric continue; 21960b57cec5SDimitry Andric } 21970b57cec5SDimitry Andric 21980b57cec5SDimitry Andric VersionTuple MergedIntroduced2 = MergedIntroduced; 21990b57cec5SDimitry Andric VersionTuple MergedDeprecated2 = MergedDeprecated; 22000b57cec5SDimitry Andric VersionTuple MergedObsoleted2 = MergedObsoleted; 22010b57cec5SDimitry Andric 22020b57cec5SDimitry Andric if (MergedIntroduced2.empty()) 22030b57cec5SDimitry Andric MergedIntroduced2 = OldIntroduced; 22040b57cec5SDimitry Andric if (MergedDeprecated2.empty()) 22050b57cec5SDimitry Andric MergedDeprecated2 = OldDeprecated; 22060b57cec5SDimitry Andric if (MergedObsoleted2.empty()) 22070b57cec5SDimitry Andric MergedObsoleted2 = OldObsoleted; 22080b57cec5SDimitry Andric 22090b57cec5SDimitry Andric if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform, 22100b57cec5SDimitry Andric MergedIntroduced2, MergedDeprecated2, 22110b57cec5SDimitry Andric MergedObsoleted2)) { 22120b57cec5SDimitry Andric Attrs.erase(Attrs.begin() + i); 22130b57cec5SDimitry Andric --e; 22140b57cec5SDimitry Andric continue; 22150b57cec5SDimitry Andric } 22160b57cec5SDimitry Andric 22170b57cec5SDimitry Andric MergedIntroduced = MergedIntroduced2; 22180b57cec5SDimitry Andric MergedDeprecated = MergedDeprecated2; 22190b57cec5SDimitry Andric MergedObsoleted = MergedObsoleted2; 22200b57cec5SDimitry Andric ++i; 22210b57cec5SDimitry Andric } 22220b57cec5SDimitry Andric } 22230b57cec5SDimitry Andric 22240b57cec5SDimitry Andric if (FoundAny && 22250b57cec5SDimitry Andric MergedIntroduced == Introduced && 22260b57cec5SDimitry Andric MergedDeprecated == Deprecated && 22270b57cec5SDimitry Andric MergedObsoleted == Obsoleted) 22280b57cec5SDimitry Andric return nullptr; 22290b57cec5SDimitry Andric 22300b57cec5SDimitry Andric // Only create a new attribute if !OverrideOrImpl, but we want to do 22310b57cec5SDimitry Andric // the checking. 2232a7dea167SDimitry Andric if (!checkAvailabilityAttr(*this, CI.getRange(), Platform, MergedIntroduced, 22330b57cec5SDimitry Andric MergedDeprecated, MergedObsoleted) && 22340b57cec5SDimitry Andric !OverrideOrImpl) { 2235a7dea167SDimitry Andric auto *Avail = ::new (Context) AvailabilityAttr( 2236a7dea167SDimitry Andric Context, CI, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable, 22370fca6ea1SDimitry Andric Message, IsStrict, Replacement, Priority, Environment); 22380b57cec5SDimitry Andric Avail->setImplicit(Implicit); 22390b57cec5SDimitry Andric return Avail; 22400b57cec5SDimitry Andric } 22410b57cec5SDimitry Andric return nullptr; 22420b57cec5SDimitry Andric } 22430b57cec5SDimitry Andric 22440b57cec5SDimitry Andric static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 2245fe6060f1SDimitry Andric if (isa<UsingDecl, UnresolvedUsingTypenameDecl, UnresolvedUsingValueDecl>( 2246fe6060f1SDimitry Andric D)) { 2247fe6060f1SDimitry Andric S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using) 2248fe6060f1SDimitry Andric << AL; 2249fe6060f1SDimitry Andric return; 2250fe6060f1SDimitry Andric } 2251fe6060f1SDimitry Andric 2252fe6060f1SDimitry Andric if (!AL.checkExactlyNumArgs(S, 1)) 22530b57cec5SDimitry Andric return; 22540b57cec5SDimitry Andric IdentifierLoc *Platform = AL.getArgAsIdent(0); 22550b57cec5SDimitry Andric 22560b57cec5SDimitry Andric IdentifierInfo *II = Platform->Ident; 22570b57cec5SDimitry Andric if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) 22580b57cec5SDimitry Andric S.Diag(Platform->Loc, diag::warn_availability_unknown_platform) 22590b57cec5SDimitry Andric << Platform->Ident; 22600b57cec5SDimitry Andric 22610b57cec5SDimitry Andric auto *ND = dyn_cast<NamedDecl>(D); 22620b57cec5SDimitry Andric if (!ND) // We warned about this already, so just return. 22630b57cec5SDimitry Andric return; 22640b57cec5SDimitry Andric 22650b57cec5SDimitry Andric AvailabilityChange Introduced = AL.getAvailabilityIntroduced(); 22660b57cec5SDimitry Andric AvailabilityChange Deprecated = AL.getAvailabilityDeprecated(); 22670b57cec5SDimitry Andric AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted(); 22680b57cec5SDimitry Andric bool IsUnavailable = AL.getUnavailableLoc().isValid(); 22690b57cec5SDimitry Andric bool IsStrict = AL.getStrictLoc().isValid(); 22700b57cec5SDimitry Andric StringRef Str; 22715f757f3fSDimitry Andric if (const auto *SE = dyn_cast_if_present<StringLiteral>(AL.getMessageExpr())) 22720b57cec5SDimitry Andric Str = SE->getString(); 22730b57cec5SDimitry Andric StringRef Replacement; 22745f757f3fSDimitry Andric if (const auto *SE = 22755f757f3fSDimitry Andric dyn_cast_if_present<StringLiteral>(AL.getReplacementExpr())) 22760b57cec5SDimitry Andric Replacement = SE->getString(); 22770b57cec5SDimitry Andric 22780b57cec5SDimitry Andric if (II->isStr("swift")) { 22790b57cec5SDimitry Andric if (Introduced.isValid() || Obsoleted.isValid() || 22800b57cec5SDimitry Andric (!IsUnavailable && !Deprecated.isValid())) { 22810b57cec5SDimitry Andric S.Diag(AL.getLoc(), 22820b57cec5SDimitry Andric diag::warn_availability_swift_unavailable_deprecated_only); 22830b57cec5SDimitry Andric return; 22840b57cec5SDimitry Andric } 22850b57cec5SDimitry Andric } 22860b57cec5SDimitry Andric 2287349cc55cSDimitry Andric if (II->isStr("fuchsia")) { 2288bdd1243dSDimitry Andric std::optional<unsigned> Min, Sub; 2289349cc55cSDimitry Andric if ((Min = Introduced.Version.getMinor()) || 2290349cc55cSDimitry Andric (Sub = Introduced.Version.getSubminor())) { 2291349cc55cSDimitry Andric S.Diag(AL.getLoc(), diag::warn_availability_fuchsia_unavailable_minor); 2292349cc55cSDimitry Andric return; 2293349cc55cSDimitry Andric } 2294349cc55cSDimitry Andric } 2295349cc55cSDimitry Andric 22960fca6ea1SDimitry Andric if (S.getLangOpts().HLSL && IsStrict) 22970fca6ea1SDimitry Andric S.Diag(AL.getStrictLoc(), diag::err_availability_unexpected_parameter) 22980fca6ea1SDimitry Andric << "strict" << /* HLSL */ 0; 22990fca6ea1SDimitry Andric 23000b57cec5SDimitry Andric int PriorityModifier = AL.isPragmaClangAttribute() 23010b57cec5SDimitry Andric ? Sema::AP_PragmaClangAttribute 23020b57cec5SDimitry Andric : Sema::AP_Explicit; 23030fca6ea1SDimitry Andric 23040fca6ea1SDimitry Andric const IdentifierLoc *EnvironmentLoc = AL.getEnvironment(); 23050fca6ea1SDimitry Andric IdentifierInfo *IIEnvironment = nullptr; 23060fca6ea1SDimitry Andric if (EnvironmentLoc) { 23070fca6ea1SDimitry Andric if (S.getLangOpts().HLSL) { 23080fca6ea1SDimitry Andric IIEnvironment = EnvironmentLoc->Ident; 23090fca6ea1SDimitry Andric if (AvailabilityAttr::getEnvironmentType( 23100fca6ea1SDimitry Andric EnvironmentLoc->Ident->getName()) == 23110fca6ea1SDimitry Andric llvm::Triple::EnvironmentType::UnknownEnvironment) 23120fca6ea1SDimitry Andric S.Diag(EnvironmentLoc->Loc, diag::warn_availability_unknown_environment) 23130fca6ea1SDimitry Andric << EnvironmentLoc->Ident; 23140fca6ea1SDimitry Andric } else { 23150fca6ea1SDimitry Andric S.Diag(EnvironmentLoc->Loc, diag::err_availability_unexpected_parameter) 23160fca6ea1SDimitry Andric << "environment" << /* C/C++ */ 1; 23170fca6ea1SDimitry Andric } 23180fca6ea1SDimitry Andric } 23190fca6ea1SDimitry Andric 23200b57cec5SDimitry Andric AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( 2321a7dea167SDimitry Andric ND, AL, II, false /*Implicit*/, Introduced.Version, Deprecated.Version, 2322a7dea167SDimitry Andric Obsoleted.Version, IsUnavailable, Str, IsStrict, Replacement, 23230fca6ea1SDimitry Andric Sema::AMK_None, PriorityModifier, IIEnvironment); 23240b57cec5SDimitry Andric if (NewAttr) 23250b57cec5SDimitry Andric D->addAttr(NewAttr); 23260b57cec5SDimitry Andric 23270b57cec5SDimitry Andric // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning 23280b57cec5SDimitry Andric // matches before the start of the watchOS platform. 23290b57cec5SDimitry Andric if (S.Context.getTargetInfo().getTriple().isWatchOS()) { 23300b57cec5SDimitry Andric IdentifierInfo *NewII = nullptr; 23310b57cec5SDimitry Andric if (II->getName() == "ios") 23320b57cec5SDimitry Andric NewII = &S.Context.Idents.get("watchos"); 23330b57cec5SDimitry Andric else if (II->getName() == "ios_app_extension") 23340b57cec5SDimitry Andric NewII = &S.Context.Idents.get("watchos_app_extension"); 23350b57cec5SDimitry Andric 23360b57cec5SDimitry Andric if (NewII) { 233704eeddc0SDimitry Andric const auto *SDKInfo = S.getDarwinSDKInfoForAvailabilityChecking(); 233804eeddc0SDimitry Andric const auto *IOSToWatchOSMapping = 233904eeddc0SDimitry Andric SDKInfo ? SDKInfo->getVersionMapping( 234004eeddc0SDimitry Andric DarwinSDKInfo::OSEnvPair::iOStoWatchOSPair()) 234104eeddc0SDimitry Andric : nullptr; 234204eeddc0SDimitry Andric 234304eeddc0SDimitry Andric auto adjustWatchOSVersion = 234404eeddc0SDimitry Andric [IOSToWatchOSMapping](VersionTuple Version) -> VersionTuple { 23450b57cec5SDimitry Andric if (Version.empty()) 23460b57cec5SDimitry Andric return Version; 234704eeddc0SDimitry Andric auto MinimumWatchOSVersion = VersionTuple(2, 0); 234804eeddc0SDimitry Andric 234904eeddc0SDimitry Andric if (IOSToWatchOSMapping) { 235004eeddc0SDimitry Andric if (auto MappedVersion = IOSToWatchOSMapping->map( 2351bdd1243dSDimitry Andric Version, MinimumWatchOSVersion, std::nullopt)) { 2352bdd1243dSDimitry Andric return *MappedVersion; 235304eeddc0SDimitry Andric } 235404eeddc0SDimitry Andric } 235504eeddc0SDimitry Andric 23560b57cec5SDimitry Andric auto Major = Version.getMajor(); 23570b57cec5SDimitry Andric auto NewMajor = Major >= 9 ? Major - 7 : 0; 23580b57cec5SDimitry Andric if (NewMajor >= 2) { 235981ad6265SDimitry Andric if (Version.getMinor()) { 236081ad6265SDimitry Andric if (Version.getSubminor()) 2361bdd1243dSDimitry Andric return VersionTuple(NewMajor, *Version.getMinor(), 2362bdd1243dSDimitry Andric *Version.getSubminor()); 23630b57cec5SDimitry Andric else 2364bdd1243dSDimitry Andric return VersionTuple(NewMajor, *Version.getMinor()); 23650b57cec5SDimitry Andric } 23660b57cec5SDimitry Andric return VersionTuple(NewMajor); 23670b57cec5SDimitry Andric } 23680b57cec5SDimitry Andric 236904eeddc0SDimitry Andric return MinimumWatchOSVersion; 23700b57cec5SDimitry Andric }; 23710b57cec5SDimitry Andric 23720b57cec5SDimitry Andric auto NewIntroduced = adjustWatchOSVersion(Introduced.Version); 23730b57cec5SDimitry Andric auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version); 23740b57cec5SDimitry Andric auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version); 23750b57cec5SDimitry Andric 23760b57cec5SDimitry Andric AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( 2377a7dea167SDimitry Andric ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, 2378a7dea167SDimitry Andric NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, 23790fca6ea1SDimitry Andric Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform, 23800fca6ea1SDimitry Andric IIEnvironment); 23810b57cec5SDimitry Andric if (NewAttr) 23820b57cec5SDimitry Andric D->addAttr(NewAttr); 23830b57cec5SDimitry Andric } 23840b57cec5SDimitry Andric } else if (S.Context.getTargetInfo().getTriple().isTvOS()) { 23850b57cec5SDimitry Andric // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning 23860b57cec5SDimitry Andric // matches before the start of the tvOS platform. 23870b57cec5SDimitry Andric IdentifierInfo *NewII = nullptr; 23880b57cec5SDimitry Andric if (II->getName() == "ios") 23890b57cec5SDimitry Andric NewII = &S.Context.Idents.get("tvos"); 23900b57cec5SDimitry Andric else if (II->getName() == "ios_app_extension") 23910b57cec5SDimitry Andric NewII = &S.Context.Idents.get("tvos_app_extension"); 23920b57cec5SDimitry Andric 23930b57cec5SDimitry Andric if (NewII) { 239404eeddc0SDimitry Andric const auto *SDKInfo = S.getDarwinSDKInfoForAvailabilityChecking(); 239504eeddc0SDimitry Andric const auto *IOSToTvOSMapping = 239604eeddc0SDimitry Andric SDKInfo ? SDKInfo->getVersionMapping( 239704eeddc0SDimitry Andric DarwinSDKInfo::OSEnvPair::iOStoTvOSPair()) 239804eeddc0SDimitry Andric : nullptr; 239904eeddc0SDimitry Andric 240004eeddc0SDimitry Andric auto AdjustTvOSVersion = 240104eeddc0SDimitry Andric [IOSToTvOSMapping](VersionTuple Version) -> VersionTuple { 240204eeddc0SDimitry Andric if (Version.empty()) 240304eeddc0SDimitry Andric return Version; 240404eeddc0SDimitry Andric 240504eeddc0SDimitry Andric if (IOSToTvOSMapping) { 2406bdd1243dSDimitry Andric if (auto MappedVersion = IOSToTvOSMapping->map( 2407bdd1243dSDimitry Andric Version, VersionTuple(0, 0), std::nullopt)) { 240881ad6265SDimitry Andric return *MappedVersion; 240904eeddc0SDimitry Andric } 241004eeddc0SDimitry Andric } 241104eeddc0SDimitry Andric return Version; 241204eeddc0SDimitry Andric }; 241304eeddc0SDimitry Andric 241404eeddc0SDimitry Andric auto NewIntroduced = AdjustTvOSVersion(Introduced.Version); 241504eeddc0SDimitry Andric auto NewDeprecated = AdjustTvOSVersion(Deprecated.Version); 241604eeddc0SDimitry Andric auto NewObsoleted = AdjustTvOSVersion(Obsoleted.Version); 241704eeddc0SDimitry Andric 24180b57cec5SDimitry Andric AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( 241904eeddc0SDimitry Andric ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, 242004eeddc0SDimitry Andric NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, 24210fca6ea1SDimitry Andric Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform, 24220fca6ea1SDimitry Andric IIEnvironment); 24230b57cec5SDimitry Andric if (NewAttr) 24240b57cec5SDimitry Andric D->addAttr(NewAttr); 24250b57cec5SDimitry Andric } 2426fe6060f1SDimitry Andric } else if (S.Context.getTargetInfo().getTriple().getOS() == 2427fe6060f1SDimitry Andric llvm::Triple::IOS && 2428fe6060f1SDimitry Andric S.Context.getTargetInfo().getTriple().isMacCatalystEnvironment()) { 2429fe6060f1SDimitry Andric auto GetSDKInfo = [&]() { 2430fe6060f1SDimitry Andric return S.getDarwinSDKInfoForAvailabilityChecking(AL.getRange().getBegin(), 2431fe6060f1SDimitry Andric "macOS"); 2432fe6060f1SDimitry Andric }; 2433fe6060f1SDimitry Andric 2434fe6060f1SDimitry Andric // Transcribe "ios" to "maccatalyst" (and add a new attribute). 2435fe6060f1SDimitry Andric IdentifierInfo *NewII = nullptr; 2436fe6060f1SDimitry Andric if (II->getName() == "ios") 2437fe6060f1SDimitry Andric NewII = &S.Context.Idents.get("maccatalyst"); 2438fe6060f1SDimitry Andric else if (II->getName() == "ios_app_extension") 2439fe6060f1SDimitry Andric NewII = &S.Context.Idents.get("maccatalyst_app_extension"); 2440fe6060f1SDimitry Andric if (NewII) { 2441fe6060f1SDimitry Andric auto MinMacCatalystVersion = [](const VersionTuple &V) { 2442fe6060f1SDimitry Andric if (V.empty()) 2443fe6060f1SDimitry Andric return V; 2444fe6060f1SDimitry Andric if (V.getMajor() < 13 || 2445fe6060f1SDimitry Andric (V.getMajor() == 13 && V.getMinor() && *V.getMinor() < 1)) 2446fe6060f1SDimitry Andric return VersionTuple(13, 1); // The min Mac Catalyst version is 13.1. 2447fe6060f1SDimitry Andric return V; 2448fe6060f1SDimitry Andric }; 2449fe6060f1SDimitry Andric AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( 245006c3fb27SDimitry Andric ND, AL, NewII, true /*Implicit*/, 2451fe6060f1SDimitry Andric MinMacCatalystVersion(Introduced.Version), 2452fe6060f1SDimitry Andric MinMacCatalystVersion(Deprecated.Version), 2453fe6060f1SDimitry Andric MinMacCatalystVersion(Obsoleted.Version), IsUnavailable, Str, 2454fe6060f1SDimitry Andric IsStrict, Replacement, Sema::AMK_None, 24550fca6ea1SDimitry Andric PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment); 2456fe6060f1SDimitry Andric if (NewAttr) 2457fe6060f1SDimitry Andric D->addAttr(NewAttr); 2458fe6060f1SDimitry Andric } else if (II->getName() == "macos" && GetSDKInfo() && 2459fe6060f1SDimitry Andric (!Introduced.Version.empty() || !Deprecated.Version.empty() || 2460fe6060f1SDimitry Andric !Obsoleted.Version.empty())) { 2461fe6060f1SDimitry Andric if (const auto *MacOStoMacCatalystMapping = 2462fe6060f1SDimitry Andric GetSDKInfo()->getVersionMapping( 2463fe6060f1SDimitry Andric DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) { 2464fe6060f1SDimitry Andric // Infer Mac Catalyst availability from the macOS availability attribute 2465fe6060f1SDimitry Andric // if it has versioned availability. Don't infer 'unavailable'. This 2466fe6060f1SDimitry Andric // inferred availability has lower priority than the other availability 2467fe6060f1SDimitry Andric // attributes that are inferred from 'ios'. 2468fe6060f1SDimitry Andric NewII = &S.Context.Idents.get("maccatalyst"); 2469fe6060f1SDimitry Andric auto RemapMacOSVersion = 2470bdd1243dSDimitry Andric [&](const VersionTuple &V) -> std::optional<VersionTuple> { 2471fe6060f1SDimitry Andric if (V.empty()) 2472bdd1243dSDimitry Andric return std::nullopt; 2473fe6060f1SDimitry Andric // API_TO_BE_DEPRECATED is 100000. 2474fe6060f1SDimitry Andric if (V.getMajor() == 100000) 2475fe6060f1SDimitry Andric return VersionTuple(100000); 2476fe6060f1SDimitry Andric // The minimum iosmac version is 13.1 2477bdd1243dSDimitry Andric return MacOStoMacCatalystMapping->map(V, VersionTuple(13, 1), 2478bdd1243dSDimitry Andric std::nullopt); 2479fe6060f1SDimitry Andric }; 2480bdd1243dSDimitry Andric std::optional<VersionTuple> NewIntroduced = 2481fe6060f1SDimitry Andric RemapMacOSVersion(Introduced.Version), 2482fe6060f1SDimitry Andric NewDeprecated = 2483fe6060f1SDimitry Andric RemapMacOSVersion(Deprecated.Version), 2484fe6060f1SDimitry Andric NewObsoleted = 2485fe6060f1SDimitry Andric RemapMacOSVersion(Obsoleted.Version); 2486fe6060f1SDimitry Andric if (NewIntroduced || NewDeprecated || NewObsoleted) { 2487fe6060f1SDimitry Andric auto VersionOrEmptyVersion = 2488bdd1243dSDimitry Andric [](const std::optional<VersionTuple> &V) -> VersionTuple { 2489fe6060f1SDimitry Andric return V ? *V : VersionTuple(); 2490fe6060f1SDimitry Andric }; 2491fe6060f1SDimitry Andric AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( 249206c3fb27SDimitry Andric ND, AL, NewII, true /*Implicit*/, 2493fe6060f1SDimitry Andric VersionOrEmptyVersion(NewIntroduced), 2494fe6060f1SDimitry Andric VersionOrEmptyVersion(NewDeprecated), 2495fe6060f1SDimitry Andric VersionOrEmptyVersion(NewObsoleted), /*IsUnavailable=*/false, Str, 2496fe6060f1SDimitry Andric IsStrict, Replacement, Sema::AMK_None, 2497fe6060f1SDimitry Andric PriorityModifier + Sema::AP_InferredFromOtherPlatform + 24980fca6ea1SDimitry Andric Sema::AP_InferredFromOtherPlatform, 24990fca6ea1SDimitry Andric IIEnvironment); 2500fe6060f1SDimitry Andric if (NewAttr) 2501fe6060f1SDimitry Andric D->addAttr(NewAttr); 2502fe6060f1SDimitry Andric } 2503fe6060f1SDimitry Andric } 2504fe6060f1SDimitry Andric } 25050b57cec5SDimitry Andric } 25060b57cec5SDimitry Andric } 25070b57cec5SDimitry Andric 25080b57cec5SDimitry Andric static void handleExternalSourceSymbolAttr(Sema &S, Decl *D, 25090b57cec5SDimitry Andric const ParsedAttr &AL) { 251006c3fb27SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 4)) 25110b57cec5SDimitry Andric return; 25120b57cec5SDimitry Andric 25130b57cec5SDimitry Andric StringRef Language; 25145f757f3fSDimitry Andric if (const auto *SE = dyn_cast_if_present<StringLiteral>(AL.getArgAsExpr(0))) 25150b57cec5SDimitry Andric Language = SE->getString(); 25160b57cec5SDimitry Andric StringRef DefinedIn; 25175f757f3fSDimitry Andric if (const auto *SE = dyn_cast_if_present<StringLiteral>(AL.getArgAsExpr(1))) 25180b57cec5SDimitry Andric DefinedIn = SE->getString(); 25190b57cec5SDimitry Andric bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr; 252006c3fb27SDimitry Andric StringRef USR; 25215f757f3fSDimitry Andric if (const auto *SE = dyn_cast_if_present<StringLiteral>(AL.getArgAsExpr(3))) 252206c3fb27SDimitry Andric USR = SE->getString(); 25230b57cec5SDimitry Andric 25240b57cec5SDimitry Andric D->addAttr(::new (S.Context) ExternalSourceSymbolAttr( 252506c3fb27SDimitry Andric S.Context, AL, Language, DefinedIn, IsGeneratedDeclaration, USR)); 25260b57cec5SDimitry Andric } 25270b57cec5SDimitry Andric 25280b57cec5SDimitry Andric template <class T> 2529a7dea167SDimitry Andric static T *mergeVisibilityAttr(Sema &S, Decl *D, const AttributeCommonInfo &CI, 2530a7dea167SDimitry Andric typename T::VisibilityType value) { 25310b57cec5SDimitry Andric T *existingAttr = D->getAttr<T>(); 25320b57cec5SDimitry Andric if (existingAttr) { 25330b57cec5SDimitry Andric typename T::VisibilityType existingValue = existingAttr->getVisibility(); 25340b57cec5SDimitry Andric if (existingValue == value) 25350b57cec5SDimitry Andric return nullptr; 25360b57cec5SDimitry Andric S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility); 2537a7dea167SDimitry Andric S.Diag(CI.getLoc(), diag::note_previous_attribute); 25380b57cec5SDimitry Andric D->dropAttr<T>(); 25390b57cec5SDimitry Andric } 2540a7dea167SDimitry Andric return ::new (S.Context) T(S.Context, CI, value); 25410b57cec5SDimitry Andric } 25420b57cec5SDimitry Andric 2543a7dea167SDimitry Andric VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, 2544a7dea167SDimitry Andric const AttributeCommonInfo &CI, 2545a7dea167SDimitry Andric VisibilityAttr::VisibilityType Vis) { 2546a7dea167SDimitry Andric return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, CI, Vis); 25470b57cec5SDimitry Andric } 25480b57cec5SDimitry Andric 2549a7dea167SDimitry Andric TypeVisibilityAttr * 2550a7dea167SDimitry Andric Sema::mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, 2551a7dea167SDimitry Andric TypeVisibilityAttr::VisibilityType Vis) { 2552a7dea167SDimitry Andric return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, CI, Vis); 25530b57cec5SDimitry Andric } 25540b57cec5SDimitry Andric 25550b57cec5SDimitry Andric static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, 25560b57cec5SDimitry Andric bool isTypeVisibility) { 25570b57cec5SDimitry Andric // Visibility attributes don't mean anything on a typedef. 25580b57cec5SDimitry Andric if (isa<TypedefNameDecl>(D)) { 25590b57cec5SDimitry Andric S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL; 25600b57cec5SDimitry Andric return; 25610b57cec5SDimitry Andric } 25620b57cec5SDimitry Andric 25630b57cec5SDimitry Andric // 'type_visibility' can only go on a type or namespace. 256406c3fb27SDimitry Andric if (isTypeVisibility && !(isa<TagDecl>(D) || isa<ObjCInterfaceDecl>(D) || 25650b57cec5SDimitry Andric isa<NamespaceDecl>(D))) { 25660b57cec5SDimitry Andric S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type) 256706c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() << ExpectedTypeOrNamespace; 25680b57cec5SDimitry Andric return; 25690b57cec5SDimitry Andric } 25700b57cec5SDimitry Andric 25710b57cec5SDimitry Andric // Check that the argument is a string literal. 25720b57cec5SDimitry Andric StringRef TypeStr; 25730b57cec5SDimitry Andric SourceLocation LiteralLoc; 25740b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc)) 25750b57cec5SDimitry Andric return; 25760b57cec5SDimitry Andric 25770b57cec5SDimitry Andric VisibilityAttr::VisibilityType type; 25780b57cec5SDimitry Andric if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) { 25790b57cec5SDimitry Andric S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL 25800b57cec5SDimitry Andric << TypeStr; 25810b57cec5SDimitry Andric return; 25820b57cec5SDimitry Andric } 25830b57cec5SDimitry Andric 25840b57cec5SDimitry Andric // Complain about attempts to use protected visibility on targets 25850b57cec5SDimitry Andric // (like Darwin) that don't support it. 25860b57cec5SDimitry Andric if (type == VisibilityAttr::Protected && 25870b57cec5SDimitry Andric !S.Context.getTargetInfo().hasProtectedVisibility()) { 25880b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_protected_visibility); 25890b57cec5SDimitry Andric type = VisibilityAttr::Default; 25900b57cec5SDimitry Andric } 25910b57cec5SDimitry Andric 25920b57cec5SDimitry Andric Attr *newAttr; 25930b57cec5SDimitry Andric if (isTypeVisibility) { 2594a7dea167SDimitry Andric newAttr = S.mergeTypeVisibilityAttr( 2595a7dea167SDimitry Andric D, AL, (TypeVisibilityAttr::VisibilityType)type); 25960b57cec5SDimitry Andric } else { 2597a7dea167SDimitry Andric newAttr = S.mergeVisibilityAttr(D, AL, type); 25980b57cec5SDimitry Andric } 25990b57cec5SDimitry Andric if (newAttr) 26000b57cec5SDimitry Andric D->addAttr(newAttr); 26010b57cec5SDimitry Andric } 26020b57cec5SDimitry Andric 26030b57cec5SDimitry Andric static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 26040b57cec5SDimitry Andric unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel; 26050b57cec5SDimitry Andric if (AL.getNumArgs() > 0) { 26060b57cec5SDimitry Andric Expr *E = AL.getArgAsExpr(0); 2607bdd1243dSDimitry Andric std::optional<llvm::APSInt> Idx = llvm::APSInt(32); 2608349cc55cSDimitry Andric if (E->isTypeDependent() || !(Idx = E->getIntegerConstantExpr(S.Context))) { 26090b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 26100b57cec5SDimitry Andric << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange(); 26110b57cec5SDimitry Andric return; 26120b57cec5SDimitry Andric } 26130b57cec5SDimitry Andric 2614e8d8bef9SDimitry Andric if (Idx->isSigned() && Idx->isNegative()) { 26150b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero) 26160b57cec5SDimitry Andric << E->getSourceRange(); 26170b57cec5SDimitry Andric return; 26180b57cec5SDimitry Andric } 26190b57cec5SDimitry Andric 2620e8d8bef9SDimitry Andric sentinel = Idx->getZExtValue(); 26210b57cec5SDimitry Andric } 26220b57cec5SDimitry Andric 26230b57cec5SDimitry Andric unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos; 26240b57cec5SDimitry Andric if (AL.getNumArgs() > 1) { 26250b57cec5SDimitry Andric Expr *E = AL.getArgAsExpr(1); 2626bdd1243dSDimitry Andric std::optional<llvm::APSInt> Idx = llvm::APSInt(32); 2627349cc55cSDimitry Andric if (E->isTypeDependent() || !(Idx = E->getIntegerConstantExpr(S.Context))) { 26280b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 26290b57cec5SDimitry Andric << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange(); 26300b57cec5SDimitry Andric return; 26310b57cec5SDimitry Andric } 2632e8d8bef9SDimitry Andric nullPos = Idx->getZExtValue(); 26330b57cec5SDimitry Andric 2634e8d8bef9SDimitry Andric if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) { 26350b57cec5SDimitry Andric // FIXME: This error message could be improved, it would be nice 26360b57cec5SDimitry Andric // to say what the bounds actually are. 26370b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) 26380b57cec5SDimitry Andric << E->getSourceRange(); 26390b57cec5SDimitry Andric return; 26400b57cec5SDimitry Andric } 26410b57cec5SDimitry Andric } 26420b57cec5SDimitry Andric 26430b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 26440b57cec5SDimitry Andric const FunctionType *FT = FD->getType()->castAs<FunctionType>(); 26450b57cec5SDimitry Andric if (isa<FunctionNoProtoType>(FT)) { 26460b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_named_arguments); 26470b57cec5SDimitry Andric return; 26480b57cec5SDimitry Andric } 26490b57cec5SDimitry Andric 26500b57cec5SDimitry Andric if (!cast<FunctionProtoType>(FT)->isVariadic()) { 26510b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; 26520b57cec5SDimitry Andric return; 26530b57cec5SDimitry Andric } 26540b57cec5SDimitry Andric } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { 26550b57cec5SDimitry Andric if (!MD->isVariadic()) { 26560b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; 26570b57cec5SDimitry Andric return; 26580b57cec5SDimitry Andric } 26590b57cec5SDimitry Andric } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { 26600b57cec5SDimitry Andric if (!BD->isVariadic()) { 26610b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; 26620b57cec5SDimitry Andric return; 26630b57cec5SDimitry Andric } 26640b57cec5SDimitry Andric } else if (const auto *V = dyn_cast<VarDecl>(D)) { 26650b57cec5SDimitry Andric QualType Ty = V->getType(); 26660b57cec5SDimitry Andric if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { 26670b57cec5SDimitry Andric const FunctionType *FT = Ty->isFunctionPointerType() 26680b57cec5SDimitry Andric ? D->getFunctionType() 2669fe6060f1SDimitry Andric : Ty->castAs<BlockPointerType>() 2670fe6060f1SDimitry Andric ->getPointeeType() 2671fe6060f1SDimitry Andric ->castAs<FunctionType>(); 26720b57cec5SDimitry Andric if (!cast<FunctionProtoType>(FT)->isVariadic()) { 26730b57cec5SDimitry Andric int m = Ty->isFunctionPointerType() ? 0 : 1; 26740b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; 26750b57cec5SDimitry Andric return; 26760b57cec5SDimitry Andric } 26770b57cec5SDimitry Andric } else { 26780b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 267906c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() 268006c3fb27SDimitry Andric << ExpectedFunctionMethodOrBlock; 26810b57cec5SDimitry Andric return; 26820b57cec5SDimitry Andric } 26830b57cec5SDimitry Andric } else { 26840b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 268506c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() 268606c3fb27SDimitry Andric << ExpectedFunctionMethodOrBlock; 26870b57cec5SDimitry Andric return; 26880b57cec5SDimitry Andric } 2689a7dea167SDimitry Andric D->addAttr(::new (S.Context) SentinelAttr(S.Context, AL, sentinel, nullPos)); 26900b57cec5SDimitry Andric } 26910b57cec5SDimitry Andric 26920b57cec5SDimitry Andric static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { 26930b57cec5SDimitry Andric if (D->getFunctionType() && 2694a7dea167SDimitry Andric D->getFunctionType()->getReturnType()->isVoidType() && 2695a7dea167SDimitry Andric !isa<CXXConstructorDecl>(D)) { 26960b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0; 26970b57cec5SDimitry Andric return; 26980b57cec5SDimitry Andric } 26990b57cec5SDimitry Andric if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) 27000b57cec5SDimitry Andric if (MD->getReturnType()->isVoidType()) { 27010b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 1; 27020b57cec5SDimitry Andric return; 27030b57cec5SDimitry Andric } 27040b57cec5SDimitry Andric 2705a7dea167SDimitry Andric StringRef Str; 2706fe6060f1SDimitry Andric if (AL.isStandardAttributeSyntax() && !AL.getScopeName()) { 27075ffd83dbSDimitry Andric // The standard attribute cannot be applied to variable declarations such 27085ffd83dbSDimitry Andric // as a function pointer. 27095ffd83dbSDimitry Andric if (isa<VarDecl>(D)) 27105ffd83dbSDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str) 271106c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() 271206c3fb27SDimitry Andric << "functions, classes, or enumerations"; 27135ffd83dbSDimitry Andric 2714a7dea167SDimitry Andric // If this is spelled as the standard C++17 attribute, but not in C++17, 2715a7dea167SDimitry Andric // warn about using it as an extension. If there are attribute arguments, 27165f757f3fSDimitry Andric // then claim it's a C++20 extension instead. 2717a7dea167SDimitry Andric // FIXME: If WG14 does not seem likely to adopt the same feature, add an 27185f757f3fSDimitry Andric // extension warning for C23 mode. 2719a7dea167SDimitry Andric const LangOptions &LO = S.getLangOpts(); 2720a7dea167SDimitry Andric if (AL.getNumArgs() == 1) { 27215ffd83dbSDimitry Andric if (LO.CPlusPlus && !LO.CPlusPlus20) 27225ffd83dbSDimitry Andric S.Diag(AL.getLoc(), diag::ext_cxx20_attr) << AL; 27230b57cec5SDimitry Andric 2724bdd1243dSDimitry Andric // Since this is spelled [[nodiscard]], get the optional string 27255f757f3fSDimitry Andric // literal. If in C++ mode, but not in C++20 mode, diagnose as an 2726a7dea167SDimitry Andric // extension. 27275f757f3fSDimitry Andric // FIXME: C23 should support this feature as well, even as an extension. 2728a7dea167SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, nullptr)) 2729a7dea167SDimitry Andric return; 2730a7dea167SDimitry Andric } else if (LO.CPlusPlus && !LO.CPlusPlus17) 2731a7dea167SDimitry Andric S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; 2732a7dea167SDimitry Andric } 2733a7dea167SDimitry Andric 273481ad6265SDimitry Andric if ((!AL.isGNUAttribute() && 273581ad6265SDimitry Andric !(AL.isStandardAttributeSyntax() && AL.isClangScope())) && 273681ad6265SDimitry Andric isa<TypedefNameDecl>(D)) { 273781ad6265SDimitry Andric S.Diag(AL.getLoc(), diag::warn_unused_result_typedef_unsupported_spelling) 273881ad6265SDimitry Andric << AL.isGNUScope(); 273981ad6265SDimitry Andric return; 274081ad6265SDimitry Andric } 274181ad6265SDimitry Andric 2742a7dea167SDimitry Andric D->addAttr(::new (S.Context) WarnUnusedResultAttr(S.Context, AL, Str)); 27430b57cec5SDimitry Andric } 27440b57cec5SDimitry Andric 27450b57cec5SDimitry Andric static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 27460b57cec5SDimitry Andric // weak_import only applies to variable & function declarations. 27470b57cec5SDimitry Andric bool isDef = false; 27480b57cec5SDimitry Andric if (!D->canBeWeakImported(isDef)) { 27490b57cec5SDimitry Andric if (isDef) 27500b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition) 27510b57cec5SDimitry Andric << "weak_import"; 27520b57cec5SDimitry Andric else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || 27530b57cec5SDimitry Andric (S.Context.getTargetInfo().getTriple().isOSDarwin() && 27540b57cec5SDimitry Andric (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { 27550b57cec5SDimitry Andric // Nothing to warn about here. 27560b57cec5SDimitry Andric } else 27570b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 275806c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() << ExpectedVariableOrFunction; 27590b57cec5SDimitry Andric 27600b57cec5SDimitry Andric return; 27610b57cec5SDimitry Andric } 27620b57cec5SDimitry Andric 2763a7dea167SDimitry Andric D->addAttr(::new (S.Context) WeakImportAttr(S.Context, AL)); 27640b57cec5SDimitry Andric } 27650b57cec5SDimitry Andric 27660b57cec5SDimitry Andric // Handles reqd_work_group_size and work_group_size_hint. 27670b57cec5SDimitry Andric template <typename WorkGroupAttr> 27680b57cec5SDimitry Andric static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { 27690b57cec5SDimitry Andric uint32_t WGSize[3]; 27700b57cec5SDimitry Andric for (unsigned i = 0; i < 3; ++i) { 27710b57cec5SDimitry Andric const Expr *E = AL.getArgAsExpr(i); 27720fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, E, WGSize[i], i, 27730b57cec5SDimitry Andric /*StrictlyUnsigned=*/true)) 27740b57cec5SDimitry Andric return; 27750b57cec5SDimitry Andric if (WGSize[i] == 0) { 27760b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero) 27770b57cec5SDimitry Andric << AL << E->getSourceRange(); 27780b57cec5SDimitry Andric return; 27790b57cec5SDimitry Andric } 27800b57cec5SDimitry Andric } 27810b57cec5SDimitry Andric 27820b57cec5SDimitry Andric WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>(); 27830b57cec5SDimitry Andric if (Existing && !(Existing->getXDim() == WGSize[0] && 27840b57cec5SDimitry Andric Existing->getYDim() == WGSize[1] && 27850b57cec5SDimitry Andric Existing->getZDim() == WGSize[2])) 27860b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; 27870b57cec5SDimitry Andric 2788a7dea167SDimitry Andric D->addAttr(::new (S.Context) 2789a7dea167SDimitry Andric WorkGroupAttr(S.Context, AL, WGSize[0], WGSize[1], WGSize[2])); 27900b57cec5SDimitry Andric } 27910b57cec5SDimitry Andric 27920b57cec5SDimitry Andric static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { 27930b57cec5SDimitry Andric if (!AL.hasParsedType()) { 27940b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; 27950b57cec5SDimitry Andric return; 27960b57cec5SDimitry Andric } 27970b57cec5SDimitry Andric 27980b57cec5SDimitry Andric TypeSourceInfo *ParmTSI = nullptr; 27990b57cec5SDimitry Andric QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI); 28000b57cec5SDimitry Andric assert(ParmTSI && "no type source info for attribute argument"); 28010b57cec5SDimitry Andric 28020b57cec5SDimitry Andric if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && 28030b57cec5SDimitry Andric (ParmType->isBooleanType() || 28040b57cec5SDimitry Andric !ParmType->isIntegralType(S.getASTContext()))) { 2805480093f4SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << 2 << AL; 28060b57cec5SDimitry Andric return; 28070b57cec5SDimitry Andric } 28080b57cec5SDimitry Andric 28090b57cec5SDimitry Andric if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) { 28100b57cec5SDimitry Andric if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) { 28110b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; 28120b57cec5SDimitry Andric return; 28130b57cec5SDimitry Andric } 28140b57cec5SDimitry Andric } 28150b57cec5SDimitry Andric 2816a7dea167SDimitry Andric D->addAttr(::new (S.Context) VecTypeHintAttr(S.Context, AL, ParmTSI)); 28170b57cec5SDimitry Andric } 28180b57cec5SDimitry Andric 2819a7dea167SDimitry Andric SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, 2820a7dea167SDimitry Andric StringRef Name) { 28210b57cec5SDimitry Andric // Explicit or partial specializations do not inherit 28220b57cec5SDimitry Andric // the section attribute from the primary template. 28230b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 2824a7dea167SDimitry Andric if (CI.getAttributeSpellingListIndex() == SectionAttr::Declspec_allocate && 28250b57cec5SDimitry Andric FD->isFunctionTemplateSpecialization()) 28260b57cec5SDimitry Andric return nullptr; 28270b57cec5SDimitry Andric } 28280b57cec5SDimitry Andric if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) { 28290b57cec5SDimitry Andric if (ExistingAttr->getName() == Name) 28300b57cec5SDimitry Andric return nullptr; 28310b57cec5SDimitry Andric Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section) 28320b57cec5SDimitry Andric << 1 /*section*/; 2833a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_previous_attribute); 28340b57cec5SDimitry Andric return nullptr; 28350b57cec5SDimitry Andric } 2836a7dea167SDimitry Andric return ::new (Context) SectionAttr(Context, CI, Name); 28370b57cec5SDimitry Andric } 28380b57cec5SDimitry Andric 2839fe6060f1SDimitry Andric llvm::Error Sema::isValidSectionSpecifier(StringRef SecName) { 2840fe6060f1SDimitry Andric if (!Context.getTargetInfo().getTriple().isOSDarwin()) 2841fe6060f1SDimitry Andric return llvm::Error::success(); 2842fe6060f1SDimitry Andric 2843fe6060f1SDimitry Andric // Let MCSectionMachO validate this. 2844fe6060f1SDimitry Andric StringRef Segment, Section; 2845fe6060f1SDimitry Andric unsigned TAA, StubSize; 2846fe6060f1SDimitry Andric bool HasTAA; 2847fe6060f1SDimitry Andric return llvm::MCSectionMachO::ParseSectionSpecifier(SecName, Segment, Section, 2848fe6060f1SDimitry Andric TAA, HasTAA, StubSize); 2849fe6060f1SDimitry Andric } 2850fe6060f1SDimitry Andric 28510b57cec5SDimitry Andric bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) { 2852fe6060f1SDimitry Andric if (llvm::Error E = isValidSectionSpecifier(SecName)) { 2853fe6060f1SDimitry Andric Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) 2854fe6060f1SDimitry Andric << toString(std::move(E)) << 1 /*'section'*/; 28550b57cec5SDimitry Andric return false; 28560b57cec5SDimitry Andric } 28570b57cec5SDimitry Andric return true; 28580b57cec5SDimitry Andric } 28590b57cec5SDimitry Andric 28600b57cec5SDimitry Andric static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 28610b57cec5SDimitry Andric // Make sure that there is a string literal as the sections's single 28620b57cec5SDimitry Andric // argument. 28630b57cec5SDimitry Andric StringRef Str; 28640b57cec5SDimitry Andric SourceLocation LiteralLoc; 28650b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) 28660b57cec5SDimitry Andric return; 28670b57cec5SDimitry Andric 28680b57cec5SDimitry Andric if (!S.checkSectionName(LiteralLoc, Str)) 28690b57cec5SDimitry Andric return; 28700b57cec5SDimitry Andric 2871a7dea167SDimitry Andric SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str); 2872e8d8bef9SDimitry Andric if (NewAttr) { 28730b57cec5SDimitry Andric D->addAttr(NewAttr); 2874e8d8bef9SDimitry Andric if (isa<FunctionDecl, FunctionTemplateDecl, ObjCMethodDecl, 2875e8d8bef9SDimitry Andric ObjCPropertyDecl>(D)) 2876e8d8bef9SDimitry Andric S.UnifySection(NewAttr->getName(), 2877e8d8bef9SDimitry Andric ASTContext::PSF_Execute | ASTContext::PSF_Read, 2878e8d8bef9SDimitry Andric cast<NamedDecl>(D)); 2879e8d8bef9SDimitry Andric } 28800b57cec5SDimitry Andric } 28810b57cec5SDimitry Andric 28821db9f3b2SDimitry Andric static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 28831db9f3b2SDimitry Andric StringRef Str; 28841db9f3b2SDimitry Andric SourceLocation LiteralLoc; 28851db9f3b2SDimitry Andric // Check that it is a string. 28861db9f3b2SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) 28871db9f3b2SDimitry Andric return; 28881db9f3b2SDimitry Andric 28891db9f3b2SDimitry Andric llvm::CodeModel::Model CM; 28901db9f3b2SDimitry Andric if (!CodeModelAttr::ConvertStrToModel(Str, CM)) { 28911db9f3b2SDimitry Andric S.Diag(LiteralLoc, diag::err_attr_codemodel_arg) << Str; 28921db9f3b2SDimitry Andric return; 28931db9f3b2SDimitry Andric } 28941db9f3b2SDimitry Andric 28951db9f3b2SDimitry Andric D->addAttr(::new (S.Context) CodeModelAttr(S.Context, AL, CM)); 28961db9f3b2SDimitry Andric } 28971db9f3b2SDimitry Andric 28980b57cec5SDimitry Andric // This is used for `__declspec(code_seg("segname"))` on a decl. 28990b57cec5SDimitry Andric // `#pragma code_seg("segname")` uses checkSectionName() instead. 29000b57cec5SDimitry Andric static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc, 29010b57cec5SDimitry Andric StringRef CodeSegName) { 2902fe6060f1SDimitry Andric if (llvm::Error E = S.isValidSectionSpecifier(CodeSegName)) { 29030b57cec5SDimitry Andric S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) 2904fe6060f1SDimitry Andric << toString(std::move(E)) << 0 /*'code-seg'*/; 29050b57cec5SDimitry Andric return false; 29060b57cec5SDimitry Andric } 29070b57cec5SDimitry Andric 29080b57cec5SDimitry Andric return true; 29090b57cec5SDimitry Andric } 29100b57cec5SDimitry Andric 2911a7dea167SDimitry Andric CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI, 2912a7dea167SDimitry Andric StringRef Name) { 29130b57cec5SDimitry Andric // Explicit or partial specializations do not inherit 29140b57cec5SDimitry Andric // the code_seg attribute from the primary template. 29150b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 29160b57cec5SDimitry Andric if (FD->isFunctionTemplateSpecialization()) 29170b57cec5SDimitry Andric return nullptr; 29180b57cec5SDimitry Andric } 29190b57cec5SDimitry Andric if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) { 29200b57cec5SDimitry Andric if (ExistingAttr->getName() == Name) 29210b57cec5SDimitry Andric return nullptr; 29220b57cec5SDimitry Andric Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section) 29230b57cec5SDimitry Andric << 0 /*codeseg*/; 2924a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_previous_attribute); 29250b57cec5SDimitry Andric return nullptr; 29260b57cec5SDimitry Andric } 2927a7dea167SDimitry Andric return ::new (Context) CodeSegAttr(Context, CI, Name); 29280b57cec5SDimitry Andric } 29290b57cec5SDimitry Andric 29300b57cec5SDimitry Andric static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 29310b57cec5SDimitry Andric StringRef Str; 29320b57cec5SDimitry Andric SourceLocation LiteralLoc; 29330b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) 29340b57cec5SDimitry Andric return; 29350b57cec5SDimitry Andric if (!checkCodeSegName(S, LiteralLoc, Str)) 29360b57cec5SDimitry Andric return; 29370b57cec5SDimitry Andric if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) { 29380b57cec5SDimitry Andric if (!ExistingAttr->isImplicit()) { 29390b57cec5SDimitry Andric S.Diag(AL.getLoc(), 29400b57cec5SDimitry Andric ExistingAttr->getName() == Str 29410b57cec5SDimitry Andric ? diag::warn_duplicate_codeseg_attribute 29420b57cec5SDimitry Andric : diag::err_conflicting_codeseg_attribute); 29430b57cec5SDimitry Andric return; 29440b57cec5SDimitry Andric } 29450b57cec5SDimitry Andric D->dropAttr<CodeSegAttr>(); 29460b57cec5SDimitry Andric } 2947a7dea167SDimitry Andric if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL, Str)) 29480b57cec5SDimitry Andric D->addAttr(CSA); 29490b57cec5SDimitry Andric } 29500b57cec5SDimitry Andric 29510b57cec5SDimitry Andric bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { 2952e8d8bef9SDimitry Andric enum FirstParam { Unsupported, Duplicate, Unknown }; 2953bdd1243dSDimitry Andric enum SecondParam { None, CPU, Tune }; 29544824e7fdSDimitry Andric enum ThirdParam { Target, TargetClones }; 2955349cc55cSDimitry Andric if (AttrStr.contains("fpmath=")) 29560b57cec5SDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 29574824e7fdSDimitry Andric << Unsupported << None << "fpmath=" << Target; 2958e8d8bef9SDimitry Andric 2959e8d8bef9SDimitry Andric // Diagnose use of tune if target doesn't support it. 2960e8d8bef9SDimitry Andric if (!Context.getTargetInfo().supportsTargetAttributeTune() && 2961349cc55cSDimitry Andric AttrStr.contains("tune=")) 2962e8d8bef9SDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 29634824e7fdSDimitry Andric << Unsupported << None << "tune=" << Target; 29640b57cec5SDimitry Andric 2965bdd1243dSDimitry Andric ParsedTargetAttr ParsedAttrs = 2966bdd1243dSDimitry Andric Context.getTargetInfo().parseTargetAttr(AttrStr); 29670b57cec5SDimitry Andric 2968bdd1243dSDimitry Andric if (!ParsedAttrs.CPU.empty() && 2969bdd1243dSDimitry Andric !Context.getTargetInfo().isValidCPUName(ParsedAttrs.CPU)) 29700b57cec5SDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 2971bdd1243dSDimitry Andric << Unknown << CPU << ParsedAttrs.CPU << Target; 2972e8d8bef9SDimitry Andric 2973e8d8bef9SDimitry Andric if (!ParsedAttrs.Tune.empty() && 2974e8d8bef9SDimitry Andric !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune)) 2975e8d8bef9SDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 29764824e7fdSDimitry Andric << Unknown << Tune << ParsedAttrs.Tune << Target; 29770b57cec5SDimitry Andric 29785f757f3fSDimitry Andric if (Context.getTargetInfo().getTriple().isRISCV() && 29795f757f3fSDimitry Andric ParsedAttrs.Duplicate != "") 29805f757f3fSDimitry Andric return Diag(LiteralLoc, diag::err_duplicate_target_attribute) 29815f757f3fSDimitry Andric << Duplicate << None << ParsedAttrs.Duplicate << Target; 29825f757f3fSDimitry Andric 2983bdd1243dSDimitry Andric if (ParsedAttrs.Duplicate != "") 29840b57cec5SDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 2985bdd1243dSDimitry Andric << Duplicate << None << ParsedAttrs.Duplicate << Target; 29860b57cec5SDimitry Andric 29870b57cec5SDimitry Andric for (const auto &Feature : ParsedAttrs.Features) { 29880b57cec5SDimitry Andric auto CurFeature = StringRef(Feature).drop_front(); // remove + or -. 29890b57cec5SDimitry Andric if (!Context.getTargetInfo().isValidFeatureName(CurFeature)) 29900b57cec5SDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 29914824e7fdSDimitry Andric << Unsupported << None << CurFeature << Target; 29920b57cec5SDimitry Andric } 29930b57cec5SDimitry Andric 29940fca6ea1SDimitry Andric TargetInfo::BranchProtectionInfo BPI{}; 29954824e7fdSDimitry Andric StringRef DiagMsg; 29964824e7fdSDimitry Andric if (ParsedAttrs.BranchProtection.empty()) 29974824e7fdSDimitry Andric return false; 29984824e7fdSDimitry Andric if (!Context.getTargetInfo().validateBranchProtection( 2999bdd1243dSDimitry Andric ParsedAttrs.BranchProtection, ParsedAttrs.CPU, BPI, DiagMsg)) { 30004824e7fdSDimitry Andric if (DiagMsg.empty()) 3001480093f4SDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 30024824e7fdSDimitry Andric << Unsupported << None << "branch-protection" << Target; 3003480093f4SDimitry Andric return Diag(LiteralLoc, diag::err_invalid_branch_protection_spec) 30044824e7fdSDimitry Andric << DiagMsg; 3005480093f4SDimitry Andric } 30064824e7fdSDimitry Andric if (!DiagMsg.empty()) 30074824e7fdSDimitry Andric Diag(LiteralLoc, diag::warn_unsupported_branch_protection_spec) << DiagMsg; 3008480093f4SDimitry Andric 30090b57cec5SDimitry Andric return false; 30100b57cec5SDimitry Andric } 30110b57cec5SDimitry Andric 30120fca6ea1SDimitry Andric bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, 30130fca6ea1SDimitry Andric StringRef AttrStr) { 3014bdd1243dSDimitry Andric enum FirstParam { Unsupported }; 3015bdd1243dSDimitry Andric enum SecondParam { None }; 3016bdd1243dSDimitry Andric enum ThirdParam { Target, TargetClones, TargetVersion }; 3017bdd1243dSDimitry Andric llvm::SmallVector<StringRef, 8> Features; 3018bdd1243dSDimitry Andric AttrStr.split(Features, "+"); 3019bdd1243dSDimitry Andric for (auto &CurFeature : Features) { 3020bdd1243dSDimitry Andric CurFeature = CurFeature.trim(); 3021bdd1243dSDimitry Andric if (CurFeature == "default") 3022bdd1243dSDimitry Andric continue; 3023bdd1243dSDimitry Andric if (!Context.getTargetInfo().validateCpuSupports(CurFeature)) 3024bdd1243dSDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 3025bdd1243dSDimitry Andric << Unsupported << None << CurFeature << TargetVersion; 3026bdd1243dSDimitry Andric } 3027bdd1243dSDimitry Andric return false; 3028bdd1243dSDimitry Andric } 3029bdd1243dSDimitry Andric 3030bdd1243dSDimitry Andric static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 3031bdd1243dSDimitry Andric StringRef Str; 3032bdd1243dSDimitry Andric SourceLocation LiteralLoc; 3033bdd1243dSDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) || 30340fca6ea1SDimitry Andric S.checkTargetVersionAttr(LiteralLoc, D, Str)) 3035bdd1243dSDimitry Andric return; 3036bdd1243dSDimitry Andric TargetVersionAttr *NewAttr = 3037bdd1243dSDimitry Andric ::new (S.Context) TargetVersionAttr(S.Context, AL, Str); 3038bdd1243dSDimitry Andric D->addAttr(NewAttr); 3039bdd1243dSDimitry Andric } 3040bdd1243dSDimitry Andric 30410b57cec5SDimitry Andric static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 30420b57cec5SDimitry Andric StringRef Str; 30430b57cec5SDimitry Andric SourceLocation LiteralLoc; 30440b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) || 30450b57cec5SDimitry Andric S.checkTargetAttr(LiteralLoc, Str)) 30460b57cec5SDimitry Andric return; 30470b57cec5SDimitry Andric 3048a7dea167SDimitry Andric TargetAttr *NewAttr = ::new (S.Context) TargetAttr(S.Context, AL, Str); 30490b57cec5SDimitry Andric D->addAttr(NewAttr); 30500b57cec5SDimitry Andric } 30510b57cec5SDimitry Andric 3052bdd1243dSDimitry Andric bool Sema::checkTargetClonesAttrString( 3053bdd1243dSDimitry Andric SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal, 30540fca6ea1SDimitry Andric Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault, 3055bdd1243dSDimitry Andric SmallVectorImpl<SmallString<64>> &StringsBuffer) { 30564824e7fdSDimitry Andric enum FirstParam { Unsupported, Duplicate, Unknown }; 3057bdd1243dSDimitry Andric enum SecondParam { None, CPU, Tune }; 30584824e7fdSDimitry Andric enum ThirdParam { Target, TargetClones }; 30594824e7fdSDimitry Andric HasCommas = HasCommas || Str.contains(','); 306006c3fb27SDimitry Andric const TargetInfo &TInfo = Context.getTargetInfo(); 30614824e7fdSDimitry Andric // Warn on empty at the beginning of a string. 30624824e7fdSDimitry Andric if (Str.size() == 0) 30634824e7fdSDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 30644824e7fdSDimitry Andric << Unsupported << None << "" << TargetClones; 30654824e7fdSDimitry Andric 30664824e7fdSDimitry Andric std::pair<StringRef, StringRef> Parts = {{}, Str}; 30674824e7fdSDimitry Andric while (!Parts.second.empty()) { 30684824e7fdSDimitry Andric Parts = Parts.second.split(','); 30694824e7fdSDimitry Andric StringRef Cur = Parts.first.trim(); 307006c3fb27SDimitry Andric SourceLocation CurLoc = 307106c3fb27SDimitry Andric Literal->getLocationOfByte(Cur.data() - Literal->getString().data(), 307206c3fb27SDimitry Andric getSourceManager(), getLangOpts(), TInfo); 30734824e7fdSDimitry Andric 30744824e7fdSDimitry Andric bool DefaultIsDupe = false; 3075bdd1243dSDimitry Andric bool HasCodeGenImpact = false; 30764824e7fdSDimitry Andric if (Cur.empty()) 30774824e7fdSDimitry Andric return Diag(CurLoc, diag::warn_unsupported_target_attribute) 30784824e7fdSDimitry Andric << Unsupported << None << "" << TargetClones; 30794824e7fdSDimitry Andric 308006c3fb27SDimitry Andric if (TInfo.getTriple().isAArch64()) { 3081bdd1243dSDimitry Andric // AArch64 target clones specific 3082bdd1243dSDimitry Andric if (Cur == "default") { 3083bdd1243dSDimitry Andric DefaultIsDupe = HasDefault; 3084bdd1243dSDimitry Andric HasDefault = true; 3085bdd1243dSDimitry Andric if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe) 3086bdd1243dSDimitry Andric Diag(CurLoc, diag::warn_target_clone_duplicate_options); 3087bdd1243dSDimitry Andric else 3088bdd1243dSDimitry Andric StringsBuffer.push_back(Cur); 3089bdd1243dSDimitry Andric } else { 3090bdd1243dSDimitry Andric std::pair<StringRef, StringRef> CurParts = {{}, Cur}; 3091bdd1243dSDimitry Andric llvm::SmallVector<StringRef, 8> CurFeatures; 3092bdd1243dSDimitry Andric while (!CurParts.second.empty()) { 3093bdd1243dSDimitry Andric CurParts = CurParts.second.split('+'); 3094bdd1243dSDimitry Andric StringRef CurFeature = CurParts.first.trim(); 309506c3fb27SDimitry Andric if (!TInfo.validateCpuSupports(CurFeature)) { 3096bdd1243dSDimitry Andric Diag(CurLoc, diag::warn_unsupported_target_attribute) 3097bdd1243dSDimitry Andric << Unsupported << None << CurFeature << TargetClones; 3098bdd1243dSDimitry Andric continue; 3099bdd1243dSDimitry Andric } 310006c3fb27SDimitry Andric if (TInfo.doesFeatureAffectCodeGen(CurFeature)) 3101bdd1243dSDimitry Andric HasCodeGenImpact = true; 3102bdd1243dSDimitry Andric CurFeatures.push_back(CurFeature); 3103bdd1243dSDimitry Andric } 3104bdd1243dSDimitry Andric // Canonize TargetClones Attributes 3105bdd1243dSDimitry Andric llvm::sort(CurFeatures); 3106bdd1243dSDimitry Andric SmallString<64> Res; 3107bdd1243dSDimitry Andric for (auto &CurFeat : CurFeatures) { 31080fca6ea1SDimitry Andric if (!Res.empty()) 3109bdd1243dSDimitry Andric Res.append("+"); 3110bdd1243dSDimitry Andric Res.append(CurFeat); 3111bdd1243dSDimitry Andric } 3112bdd1243dSDimitry Andric if (llvm::is_contained(StringsBuffer, Res) || DefaultIsDupe) 3113bdd1243dSDimitry Andric Diag(CurLoc, diag::warn_target_clone_duplicate_options); 3114bdd1243dSDimitry Andric else if (!HasCodeGenImpact) 3115bdd1243dSDimitry Andric // Ignore features in target_clone attribute that don't impact 3116bdd1243dSDimitry Andric // code generation 3117bdd1243dSDimitry Andric Diag(CurLoc, diag::warn_target_clone_no_impact_options); 3118bdd1243dSDimitry Andric else if (!Res.empty()) { 3119bdd1243dSDimitry Andric StringsBuffer.push_back(Res); 3120bdd1243dSDimitry Andric HasNotDefault = true; 3121bdd1243dSDimitry Andric } 3122bdd1243dSDimitry Andric } 3123bdd1243dSDimitry Andric } else { 3124bdd1243dSDimitry Andric // Other targets ( currently X86 ) 31255f757f3fSDimitry Andric if (Cur.starts_with("arch=")) { 31264824e7fdSDimitry Andric if (!Context.getTargetInfo().isValidCPUName( 31274824e7fdSDimitry Andric Cur.drop_front(sizeof("arch=") - 1))) 31284824e7fdSDimitry Andric return Diag(CurLoc, diag::warn_unsupported_target_attribute) 3129bdd1243dSDimitry Andric << Unsupported << CPU << Cur.drop_front(sizeof("arch=") - 1) 3130bdd1243dSDimitry Andric << TargetClones; 31314824e7fdSDimitry Andric } else if (Cur == "default") { 31324824e7fdSDimitry Andric DefaultIsDupe = HasDefault; 31334824e7fdSDimitry Andric HasDefault = true; 31344824e7fdSDimitry Andric } else if (!Context.getTargetInfo().isValidFeatureName(Cur)) 31354824e7fdSDimitry Andric return Diag(CurLoc, diag::warn_unsupported_target_attribute) 31364824e7fdSDimitry Andric << Unsupported << None << Cur << TargetClones; 3137bdd1243dSDimitry Andric if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe) 31384824e7fdSDimitry Andric Diag(CurLoc, diag::warn_target_clone_duplicate_options); 31394824e7fdSDimitry Andric // Note: Add even if there are duplicates, since it changes name mangling. 3140bdd1243dSDimitry Andric StringsBuffer.push_back(Cur); 31414824e7fdSDimitry Andric } 3142bdd1243dSDimitry Andric } 31435f757f3fSDimitry Andric if (Str.rtrim().ends_with(",")) 31444824e7fdSDimitry Andric return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) 31454824e7fdSDimitry Andric << Unsupported << None << "" << TargetClones; 31464824e7fdSDimitry Andric return false; 31474824e7fdSDimitry Andric } 31484824e7fdSDimitry Andric 31494824e7fdSDimitry Andric static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 3150bdd1243dSDimitry Andric if (S.Context.getTargetInfo().getTriple().isAArch64() && 3151bdd1243dSDimitry Andric !S.Context.getTargetInfo().hasFeature("fmv")) 3152bdd1243dSDimitry Andric return; 3153bdd1243dSDimitry Andric 31544824e7fdSDimitry Andric // Ensure we don't combine these with themselves, since that causes some 31554824e7fdSDimitry Andric // confusing behavior. 31564824e7fdSDimitry Andric if (const auto *Other = D->getAttr<TargetClonesAttr>()) { 31574824e7fdSDimitry Andric S.Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << AL; 31584824e7fdSDimitry Andric S.Diag(Other->getLocation(), diag::note_conflicting_attribute); 31594824e7fdSDimitry Andric return; 31604824e7fdSDimitry Andric } 31614824e7fdSDimitry Andric if (checkAttrMutualExclusion<TargetClonesAttr>(S, D, AL)) 31624824e7fdSDimitry Andric return; 31634824e7fdSDimitry Andric 31644824e7fdSDimitry Andric SmallVector<StringRef, 2> Strings; 3165bdd1243dSDimitry Andric SmallVector<SmallString<64>, 2> StringsBuffer; 3166bdd1243dSDimitry Andric bool HasCommas = false, HasDefault = false, HasNotDefault = false; 31674824e7fdSDimitry Andric 31684824e7fdSDimitry Andric for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { 31694824e7fdSDimitry Andric StringRef CurStr; 31704824e7fdSDimitry Andric SourceLocation LiteralLoc; 31714824e7fdSDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, I, CurStr, &LiteralLoc) || 31724824e7fdSDimitry Andric S.checkTargetClonesAttrString( 31734824e7fdSDimitry Andric LiteralLoc, CurStr, 31740fca6ea1SDimitry Andric cast<StringLiteral>(AL.getArgAsExpr(I)->IgnoreParenCasts()), D, 3175bdd1243dSDimitry Andric HasDefault, HasCommas, HasNotDefault, StringsBuffer)) 31764824e7fdSDimitry Andric return; 31774824e7fdSDimitry Andric } 3178bdd1243dSDimitry Andric for (auto &SmallStr : StringsBuffer) 3179bdd1243dSDimitry Andric Strings.push_back(SmallStr.str()); 31804824e7fdSDimitry Andric 31814824e7fdSDimitry Andric if (HasCommas && AL.getNumArgs() > 1) 31824824e7fdSDimitry Andric S.Diag(AL.getLoc(), diag::warn_target_clone_mixed_values); 31834824e7fdSDimitry Andric 3184bdd1243dSDimitry Andric if (S.Context.getTargetInfo().getTriple().isAArch64() && !HasDefault) { 3185bdd1243dSDimitry Andric // Add default attribute if there is no one 3186bdd1243dSDimitry Andric HasDefault = true; 3187bdd1243dSDimitry Andric Strings.push_back("default"); 3188bdd1243dSDimitry Andric } 3189bdd1243dSDimitry Andric 31904824e7fdSDimitry Andric if (!HasDefault) { 31914824e7fdSDimitry Andric S.Diag(AL.getLoc(), diag::err_target_clone_must_have_default); 31924824e7fdSDimitry Andric return; 31934824e7fdSDimitry Andric } 31944824e7fdSDimitry Andric 31954824e7fdSDimitry Andric // FIXME: We could probably figure out how to get this to work for lambdas 31964824e7fdSDimitry Andric // someday. 31974824e7fdSDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { 31984824e7fdSDimitry Andric if (MD->getParent()->isLambda()) { 31994824e7fdSDimitry Andric S.Diag(D->getLocation(), diag::err_multiversion_doesnt_support) 32004824e7fdSDimitry Andric << static_cast<unsigned>(MultiVersionKind::TargetClones) 32014824e7fdSDimitry Andric << /*Lambda*/ 9; 32024824e7fdSDimitry Andric return; 32034824e7fdSDimitry Andric } 32044824e7fdSDimitry Andric } 32054824e7fdSDimitry Andric 3206bdd1243dSDimitry Andric // No multiversion if we have default version only. 3207bdd1243dSDimitry Andric if (S.Context.getTargetInfo().getTriple().isAArch64() && !HasNotDefault) 3208bdd1243dSDimitry Andric return; 3209bdd1243dSDimitry Andric 32104824e7fdSDimitry Andric cast<FunctionDecl>(D)->setIsMultiVersion(); 32114824e7fdSDimitry Andric TargetClonesAttr *NewAttr = ::new (S.Context) 32124824e7fdSDimitry Andric TargetClonesAttr(S.Context, AL, Strings.data(), Strings.size()); 32134824e7fdSDimitry Andric D->addAttr(NewAttr); 32144824e7fdSDimitry Andric } 32154824e7fdSDimitry Andric 32160b57cec5SDimitry Andric static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 32170b57cec5SDimitry Andric Expr *E = AL.getArgAsExpr(0); 32180b57cec5SDimitry Andric uint32_t VecWidth; 32190fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, E, VecWidth)) { 32200b57cec5SDimitry Andric AL.setInvalid(); 32210b57cec5SDimitry Andric return; 32220b57cec5SDimitry Andric } 32230b57cec5SDimitry Andric 32240b57cec5SDimitry Andric MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>(); 32250b57cec5SDimitry Andric if (Existing && Existing->getVectorWidth() != VecWidth) { 32260b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; 32270b57cec5SDimitry Andric return; 32280b57cec5SDimitry Andric } 32290b57cec5SDimitry Andric 3230a7dea167SDimitry Andric D->addAttr(::new (S.Context) MinVectorWidthAttr(S.Context, AL, VecWidth)); 32310b57cec5SDimitry Andric } 32320b57cec5SDimitry Andric 32330b57cec5SDimitry Andric static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 32340b57cec5SDimitry Andric Expr *E = AL.getArgAsExpr(0); 32350b57cec5SDimitry Andric SourceLocation Loc = E->getExprLoc(); 32360b57cec5SDimitry Andric FunctionDecl *FD = nullptr; 32370b57cec5SDimitry Andric DeclarationNameInfo NI; 32380b57cec5SDimitry Andric 32390b57cec5SDimitry Andric // gcc only allows for simple identifiers. Since we support more than gcc, we 32400b57cec5SDimitry Andric // will warn the user. 32410b57cec5SDimitry Andric if (auto *DRE = dyn_cast<DeclRefExpr>(E)) { 32420b57cec5SDimitry Andric if (DRE->hasQualifier()) 32430b57cec5SDimitry Andric S.Diag(Loc, diag::warn_cleanup_ext); 32440b57cec5SDimitry Andric FD = dyn_cast<FunctionDecl>(DRE->getDecl()); 32450b57cec5SDimitry Andric NI = DRE->getNameInfo(); 32460b57cec5SDimitry Andric if (!FD) { 32470b57cec5SDimitry Andric S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1 32480b57cec5SDimitry Andric << NI.getName(); 32490b57cec5SDimitry Andric return; 32500b57cec5SDimitry Andric } 32510b57cec5SDimitry Andric } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { 32520b57cec5SDimitry Andric if (ULE->hasExplicitTemplateArgs()) 32530b57cec5SDimitry Andric S.Diag(Loc, diag::warn_cleanup_ext); 32540b57cec5SDimitry Andric FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); 32550b57cec5SDimitry Andric NI = ULE->getNameInfo(); 32560b57cec5SDimitry Andric if (!FD) { 32570b57cec5SDimitry Andric S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2 32580b57cec5SDimitry Andric << NI.getName(); 32590b57cec5SDimitry Andric if (ULE->getType() == S.Context.OverloadTy) 32600b57cec5SDimitry Andric S.NoteAllOverloadCandidates(ULE); 32610b57cec5SDimitry Andric return; 32620b57cec5SDimitry Andric } 32630b57cec5SDimitry Andric } else { 32640b57cec5SDimitry Andric S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0; 32650b57cec5SDimitry Andric return; 32660b57cec5SDimitry Andric } 32670b57cec5SDimitry Andric 32680b57cec5SDimitry Andric if (FD->getNumParams() != 1) { 32690b57cec5SDimitry Andric S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg) 32700b57cec5SDimitry Andric << NI.getName(); 32710b57cec5SDimitry Andric return; 32720b57cec5SDimitry Andric } 32730b57cec5SDimitry Andric 32740b57cec5SDimitry Andric // We're currently more strict than GCC about what function types we accept. 32750b57cec5SDimitry Andric // If this ever proves to be a problem it should be easy to fix. 32760b57cec5SDimitry Andric QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType()); 32770b57cec5SDimitry Andric QualType ParamTy = FD->getParamDecl(0)->getType(); 32780b57cec5SDimitry Andric if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), 32790b57cec5SDimitry Andric ParamTy, Ty) != Sema::Compatible) { 32800b57cec5SDimitry Andric S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) 32810b57cec5SDimitry Andric << NI.getName() << ParamTy << Ty; 32820b57cec5SDimitry Andric return; 32830b57cec5SDimitry Andric } 32840fca6ea1SDimitry Andric VarDecl *VD = cast<VarDecl>(D); 32850fca6ea1SDimitry Andric // Create a reference to the variable declaration. This is a fake/dummy 32860fca6ea1SDimitry Andric // reference. 32870fca6ea1SDimitry Andric DeclRefExpr *VariableReference = DeclRefExpr::Create( 32880fca6ea1SDimitry Andric S.Context, NestedNameSpecifierLoc{}, FD->getLocation(), VD, false, 32890fca6ea1SDimitry Andric DeclarationNameInfo{VD->getDeclName(), VD->getLocation()}, VD->getType(), 32900fca6ea1SDimitry Andric VK_LValue); 32910fca6ea1SDimitry Andric 32920fca6ea1SDimitry Andric // Create a unary operator expression that represents taking the address of 32930fca6ea1SDimitry Andric // the variable. This is a fake/dummy expression. 32940fca6ea1SDimitry Andric Expr *AddressOfVariable = UnaryOperator::Create( 32950fca6ea1SDimitry Andric S.Context, VariableReference, UnaryOperatorKind::UO_AddrOf, 32960fca6ea1SDimitry Andric S.Context.getPointerType(VD->getType()), VK_PRValue, OK_Ordinary, Loc, 32970fca6ea1SDimitry Andric +false, FPOptionsOverride{}); 32980fca6ea1SDimitry Andric 32990fca6ea1SDimitry Andric // Create a function call expression. This is a fake/dummy call expression. 33000fca6ea1SDimitry Andric CallExpr *FunctionCallExpression = 33010fca6ea1SDimitry Andric CallExpr::Create(S.Context, E, ArrayRef{AddressOfVariable}, 33020fca6ea1SDimitry Andric S.Context.VoidTy, VK_PRValue, Loc, FPOptionsOverride{}); 33030fca6ea1SDimitry Andric 33040fca6ea1SDimitry Andric if (S.CheckFunctionCall(FD, FunctionCallExpression, 33050fca6ea1SDimitry Andric FD->getType()->getAs<FunctionProtoType>())) { 33060fca6ea1SDimitry Andric return; 33070fca6ea1SDimitry Andric } 33080b57cec5SDimitry Andric 3309a7dea167SDimitry Andric D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD)); 33100b57cec5SDimitry Andric } 33110b57cec5SDimitry Andric 33120b57cec5SDimitry Andric static void handleEnumExtensibilityAttr(Sema &S, Decl *D, 33130b57cec5SDimitry Andric const ParsedAttr &AL) { 33140b57cec5SDimitry Andric if (!AL.isArgIdent(0)) { 33150b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 33160b57cec5SDimitry Andric << AL << 0 << AANT_ArgumentIdentifier; 33170b57cec5SDimitry Andric return; 33180b57cec5SDimitry Andric } 33190b57cec5SDimitry Andric 33200b57cec5SDimitry Andric EnumExtensibilityAttr::Kind ExtensibilityKind; 33210b57cec5SDimitry Andric IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; 33220b57cec5SDimitry Andric if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(), 33230b57cec5SDimitry Andric ExtensibilityKind)) { 33240b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; 33250b57cec5SDimitry Andric return; 33260b57cec5SDimitry Andric } 33270b57cec5SDimitry Andric 3328a7dea167SDimitry Andric D->addAttr(::new (S.Context) 3329a7dea167SDimitry Andric EnumExtensibilityAttr(S.Context, AL, ExtensibilityKind)); 33300b57cec5SDimitry Andric } 33310b57cec5SDimitry Andric 33320b57cec5SDimitry Andric /// Handle __attribute__((format_arg((idx)))) attribute based on 33330b57cec5SDimitry Andric /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 33340b57cec5SDimitry Andric static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 333506c3fb27SDimitry Andric const Expr *IdxExpr = AL.getArgAsExpr(0); 33360b57cec5SDimitry Andric ParamIdx Idx; 33370fca6ea1SDimitry Andric if (!S.checkFunctionOrMethodParameterIndex(D, AL, 1, IdxExpr, Idx)) 33380b57cec5SDimitry Andric return; 33390b57cec5SDimitry Andric 33400b57cec5SDimitry Andric // Make sure the format string is really a string. 33410b57cec5SDimitry Andric QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); 33420b57cec5SDimitry Andric 33430fca6ea1SDimitry Andric bool NotNSStringTy = !S.ObjC().isNSStringType(Ty); 33440fca6ea1SDimitry Andric if (NotNSStringTy && !S.ObjC().isCFStringType(Ty) && 33450b57cec5SDimitry Andric (!Ty->isPointerType() || 3346a7dea167SDimitry Andric !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) { 33470b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_format_attribute_not) 334881ad6265SDimitry Andric << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0); 33490b57cec5SDimitry Andric return; 33500b57cec5SDimitry Andric } 33510b57cec5SDimitry Andric Ty = getFunctionOrMethodResultType(D); 3352349cc55cSDimitry Andric // replace instancetype with the class type 3353349cc55cSDimitry Andric auto Instancetype = S.Context.getObjCInstanceTypeDecl()->getTypeForDecl(); 3354349cc55cSDimitry Andric if (Ty->getAs<TypedefType>() == Instancetype) 3355349cc55cSDimitry Andric if (auto *OMD = dyn_cast<ObjCMethodDecl>(D)) 3356349cc55cSDimitry Andric if (auto *Interface = OMD->getClassInterface()) 3357349cc55cSDimitry Andric Ty = S.Context.getObjCObjectPointerType( 3358349cc55cSDimitry Andric QualType(Interface->getTypeForDecl(), 0)); 33590fca6ea1SDimitry Andric if (!S.ObjC().isNSStringType(Ty, /*AllowNSAttributedString=*/true) && 33600fca6ea1SDimitry Andric !S.ObjC().isCFStringType(Ty) && 33610b57cec5SDimitry Andric (!Ty->isPointerType() || 3362a7dea167SDimitry Andric !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) { 33630b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_format_attribute_result_not) 33640b57cec5SDimitry Andric << (NotNSStringTy ? "string type" : "NSString") 33650b57cec5SDimitry Andric << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0); 33660b57cec5SDimitry Andric return; 33670b57cec5SDimitry Andric } 33680b57cec5SDimitry Andric 3369a7dea167SDimitry Andric D->addAttr(::new (S.Context) FormatArgAttr(S.Context, AL, Idx)); 33700b57cec5SDimitry Andric } 33710b57cec5SDimitry Andric 33720b57cec5SDimitry Andric enum FormatAttrKind { 33730b57cec5SDimitry Andric CFStringFormat, 33740b57cec5SDimitry Andric NSStringFormat, 33750b57cec5SDimitry Andric StrftimeFormat, 33760b57cec5SDimitry Andric SupportedFormat, 33770b57cec5SDimitry Andric IgnoredFormat, 33780b57cec5SDimitry Andric InvalidFormat 33790b57cec5SDimitry Andric }; 33800b57cec5SDimitry Andric 33810b57cec5SDimitry Andric /// getFormatAttrKind - Map from format attribute names to supported format 33820b57cec5SDimitry Andric /// types. 33830b57cec5SDimitry Andric static FormatAttrKind getFormatAttrKind(StringRef Format) { 33840b57cec5SDimitry Andric return llvm::StringSwitch<FormatAttrKind>(Format) 33850b57cec5SDimitry Andric // Check for formats that get handled specially. 33860b57cec5SDimitry Andric .Case("NSString", NSStringFormat) 33870b57cec5SDimitry Andric .Case("CFString", CFStringFormat) 33880b57cec5SDimitry Andric .Case("strftime", StrftimeFormat) 33890b57cec5SDimitry Andric 33900b57cec5SDimitry Andric // Otherwise, check for supported formats. 33910b57cec5SDimitry Andric .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) 33920b57cec5SDimitry Andric .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) 33930b57cec5SDimitry Andric .Case("kprintf", SupportedFormat) // OpenBSD. 33940b57cec5SDimitry Andric .Case("freebsd_kprintf", SupportedFormat) // FreeBSD. 33950b57cec5SDimitry Andric .Case("os_trace", SupportedFormat) 33960b57cec5SDimitry Andric .Case("os_log", SupportedFormat) 33970b57cec5SDimitry Andric 33980b57cec5SDimitry Andric .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) 33990b57cec5SDimitry Andric .Default(InvalidFormat); 34000b57cec5SDimitry Andric } 34010b57cec5SDimitry Andric 34020b57cec5SDimitry Andric /// Handle __attribute__((init_priority(priority))) attributes based on 34030b57cec5SDimitry Andric /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html 34040b57cec5SDimitry Andric static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 34050b57cec5SDimitry Andric if (!S.getLangOpts().CPlusPlus) { 34060b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; 34070b57cec5SDimitry Andric return; 34080b57cec5SDimitry Andric } 34090b57cec5SDimitry Andric 3410bdd1243dSDimitry Andric if (S.getLangOpts().HLSL) { 3411bdd1243dSDimitry Andric S.Diag(AL.getLoc(), diag::err_hlsl_init_priority_unsupported); 3412bdd1243dSDimitry Andric return; 3413bdd1243dSDimitry Andric } 3414bdd1243dSDimitry Andric 34150b57cec5SDimitry Andric if (S.getCurFunctionOrMethodDecl()) { 34160b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_init_priority_object_attr); 34170b57cec5SDimitry Andric AL.setInvalid(); 34180b57cec5SDimitry Andric return; 34190b57cec5SDimitry Andric } 34200b57cec5SDimitry Andric QualType T = cast<VarDecl>(D)->getType(); 34210b57cec5SDimitry Andric if (S.Context.getAsArrayType(T)) 34220b57cec5SDimitry Andric T = S.Context.getBaseElementType(T); 34230b57cec5SDimitry Andric if (!T->getAs<RecordType>()) { 34240b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_init_priority_object_attr); 34250b57cec5SDimitry Andric AL.setInvalid(); 34260b57cec5SDimitry Andric return; 34270b57cec5SDimitry Andric } 34280b57cec5SDimitry Andric 34290b57cec5SDimitry Andric Expr *E = AL.getArgAsExpr(0); 34300b57cec5SDimitry Andric uint32_t prioritynum; 34310fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, E, prioritynum)) { 34320b57cec5SDimitry Andric AL.setInvalid(); 34330b57cec5SDimitry Andric return; 34340b57cec5SDimitry Andric } 34350b57cec5SDimitry Andric 3436eaeb601bSDimitry Andric // Only perform the priority check if the attribute is outside of a system 3437eaeb601bSDimitry Andric // header. Values <= 100 are reserved for the implementation, and libc++ 3438eaeb601bSDimitry Andric // benefits from being able to specify values in that range. 3439eaeb601bSDimitry Andric if ((prioritynum < 101 || prioritynum > 65535) && 3440eaeb601bSDimitry Andric !S.getSourceManager().isInSystemHeader(AL.getLoc())) { 34410b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range) 34420b57cec5SDimitry Andric << E->getSourceRange() << AL << 101 << 65535; 34430b57cec5SDimitry Andric AL.setInvalid(); 34440b57cec5SDimitry Andric return; 34450b57cec5SDimitry Andric } 3446a7dea167SDimitry Andric D->addAttr(::new (S.Context) InitPriorityAttr(S.Context, AL, prioritynum)); 34470b57cec5SDimitry Andric } 34480b57cec5SDimitry Andric 3449349cc55cSDimitry Andric ErrorAttr *Sema::mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI, 3450349cc55cSDimitry Andric StringRef NewUserDiagnostic) { 3451349cc55cSDimitry Andric if (const auto *EA = D->getAttr<ErrorAttr>()) { 3452349cc55cSDimitry Andric std::string NewAttr = CI.getNormalizedFullName(); 3453349cc55cSDimitry Andric assert((NewAttr == "error" || NewAttr == "warning") && 3454349cc55cSDimitry Andric "unexpected normalized full name"); 3455349cc55cSDimitry Andric bool Match = (EA->isError() && NewAttr == "error") || 3456349cc55cSDimitry Andric (EA->isWarning() && NewAttr == "warning"); 3457349cc55cSDimitry Andric if (!Match) { 3458349cc55cSDimitry Andric Diag(EA->getLocation(), diag::err_attributes_are_not_compatible) 345906c3fb27SDimitry Andric << CI << EA 346006c3fb27SDimitry Andric << (CI.isRegularKeywordAttribute() || 346106c3fb27SDimitry Andric EA->isRegularKeywordAttribute()); 3462349cc55cSDimitry Andric Diag(CI.getLoc(), diag::note_conflicting_attribute); 3463349cc55cSDimitry Andric return nullptr; 3464349cc55cSDimitry Andric } 3465349cc55cSDimitry Andric if (EA->getUserDiagnostic() != NewUserDiagnostic) { 3466349cc55cSDimitry Andric Diag(CI.getLoc(), diag::warn_duplicate_attribute) << EA; 3467349cc55cSDimitry Andric Diag(EA->getLoc(), diag::note_previous_attribute); 3468349cc55cSDimitry Andric } 3469349cc55cSDimitry Andric D->dropAttr<ErrorAttr>(); 3470349cc55cSDimitry Andric } 3471349cc55cSDimitry Andric return ::new (Context) ErrorAttr(Context, CI, NewUserDiagnostic); 3472349cc55cSDimitry Andric } 3473349cc55cSDimitry Andric 3474a7dea167SDimitry Andric FormatAttr *Sema::mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI, 34750b57cec5SDimitry Andric IdentifierInfo *Format, int FormatIdx, 3476a7dea167SDimitry Andric int FirstArg) { 34770b57cec5SDimitry Andric // Check whether we already have an equivalent format attribute. 34780b57cec5SDimitry Andric for (auto *F : D->specific_attrs<FormatAttr>()) { 34790b57cec5SDimitry Andric if (F->getType() == Format && 34800b57cec5SDimitry Andric F->getFormatIdx() == FormatIdx && 34810b57cec5SDimitry Andric F->getFirstArg() == FirstArg) { 34820b57cec5SDimitry Andric // If we don't have a valid location for this attribute, adopt the 34830b57cec5SDimitry Andric // location. 34840b57cec5SDimitry Andric if (F->getLocation().isInvalid()) 3485a7dea167SDimitry Andric F->setRange(CI.getRange()); 34860b57cec5SDimitry Andric return nullptr; 34870b57cec5SDimitry Andric } 34880b57cec5SDimitry Andric } 34890b57cec5SDimitry Andric 3490a7dea167SDimitry Andric return ::new (Context) FormatAttr(Context, CI, Format, FormatIdx, FirstArg); 34910b57cec5SDimitry Andric } 34920b57cec5SDimitry Andric 34930b57cec5SDimitry Andric /// Handle __attribute__((format(type,idx,firstarg))) attributes based on 34940b57cec5SDimitry Andric /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 34950b57cec5SDimitry Andric static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 34960b57cec5SDimitry Andric if (!AL.isArgIdent(0)) { 34970b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 34980b57cec5SDimitry Andric << AL << 1 << AANT_ArgumentIdentifier; 34990b57cec5SDimitry Andric return; 35000b57cec5SDimitry Andric } 35010b57cec5SDimitry Andric 35020b57cec5SDimitry Andric // In C++ the implicit 'this' function parameter also counts, and they are 35030b57cec5SDimitry Andric // counted from one. 35040b57cec5SDimitry Andric bool HasImplicitThisParam = isInstanceMethod(D); 35050b57cec5SDimitry Andric unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam; 35060b57cec5SDimitry Andric 35070b57cec5SDimitry Andric IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; 35080b57cec5SDimitry Andric StringRef Format = II->getName(); 35090b57cec5SDimitry Andric 35100b57cec5SDimitry Andric if (normalizeName(Format)) { 35110b57cec5SDimitry Andric // If we've modified the string name, we need a new identifier for it. 35120b57cec5SDimitry Andric II = &S.Context.Idents.get(Format); 35130b57cec5SDimitry Andric } 35140b57cec5SDimitry Andric 35150b57cec5SDimitry Andric // Check for supported formats. 35160b57cec5SDimitry Andric FormatAttrKind Kind = getFormatAttrKind(Format); 35170b57cec5SDimitry Andric 35180b57cec5SDimitry Andric if (Kind == IgnoredFormat) 35190b57cec5SDimitry Andric return; 35200b57cec5SDimitry Andric 35210b57cec5SDimitry Andric if (Kind == InvalidFormat) { 35220b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) 35230b57cec5SDimitry Andric << AL << II->getName(); 35240b57cec5SDimitry Andric return; 35250b57cec5SDimitry Andric } 35260b57cec5SDimitry Andric 35270b57cec5SDimitry Andric // checks for the 2nd argument 35280b57cec5SDimitry Andric Expr *IdxExpr = AL.getArgAsExpr(1); 35290b57cec5SDimitry Andric uint32_t Idx; 35300fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, IdxExpr, Idx, 2)) 35310b57cec5SDimitry Andric return; 35320b57cec5SDimitry Andric 35330b57cec5SDimitry Andric if (Idx < 1 || Idx > NumArgs) { 35340b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) 35350b57cec5SDimitry Andric << AL << 2 << IdxExpr->getSourceRange(); 35360b57cec5SDimitry Andric return; 35370b57cec5SDimitry Andric } 35380b57cec5SDimitry Andric 35390b57cec5SDimitry Andric // FIXME: Do we need to bounds check? 35400b57cec5SDimitry Andric unsigned ArgIdx = Idx - 1; 35410b57cec5SDimitry Andric 35420b57cec5SDimitry Andric if (HasImplicitThisParam) { 35430b57cec5SDimitry Andric if (ArgIdx == 0) { 35440b57cec5SDimitry Andric S.Diag(AL.getLoc(), 35450b57cec5SDimitry Andric diag::err_format_attribute_implicit_this_format_string) 35460b57cec5SDimitry Andric << IdxExpr->getSourceRange(); 35470b57cec5SDimitry Andric return; 35480b57cec5SDimitry Andric } 35490b57cec5SDimitry Andric ArgIdx--; 35500b57cec5SDimitry Andric } 35510b57cec5SDimitry Andric 35520b57cec5SDimitry Andric // make sure the format string is really a string 35530b57cec5SDimitry Andric QualType Ty = getFunctionOrMethodParamType(D, ArgIdx); 35540b57cec5SDimitry Andric 35550fca6ea1SDimitry Andric if (!S.ObjC().isNSStringType(Ty, true) && !S.ObjC().isCFStringType(Ty) && 355681ad6265SDimitry Andric (!Ty->isPointerType() || 355781ad6265SDimitry Andric !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) { 35580b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_format_attribute_not) 355981ad6265SDimitry Andric << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, ArgIdx); 35600b57cec5SDimitry Andric return; 35610b57cec5SDimitry Andric } 35620b57cec5SDimitry Andric 35630b57cec5SDimitry Andric // check the 3rd argument 35640b57cec5SDimitry Andric Expr *FirstArgExpr = AL.getArgAsExpr(2); 35650b57cec5SDimitry Andric uint32_t FirstArg; 35660fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, FirstArgExpr, FirstArg, 3)) 35670b57cec5SDimitry Andric return; 35680b57cec5SDimitry Andric 3569bdd1243dSDimitry Andric // FirstArg == 0 is is always valid. 35700b57cec5SDimitry Andric if (FirstArg != 0) { 35710b57cec5SDimitry Andric if (Kind == StrftimeFormat) { 3572bdd1243dSDimitry Andric // If the kind is strftime, FirstArg must be 0 because strftime does not 3573bdd1243dSDimitry Andric // use any variadic arguments. 35740b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter) 3575bdd1243dSDimitry Andric << FirstArgExpr->getSourceRange() 3576bdd1243dSDimitry Andric << FixItHint::CreateReplacement(FirstArgExpr->getSourceRange(), "0"); 3577bdd1243dSDimitry Andric return; 3578bdd1243dSDimitry Andric } else if (isFunctionOrMethodVariadic(D)) { 3579bdd1243dSDimitry Andric // Else, if the function is variadic, then FirstArg must be 0 or the 3580bdd1243dSDimitry Andric // "position" of the ... parameter. It's unusual to use 0 with variadic 3581bdd1243dSDimitry Andric // functions, so the fixit proposes the latter. 3582bdd1243dSDimitry Andric if (FirstArg != NumArgs + 1) { 3583bdd1243dSDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) 3584bdd1243dSDimitry Andric << AL << 3 << FirstArgExpr->getSourceRange() 3585bdd1243dSDimitry Andric << FixItHint::CreateReplacement(FirstArgExpr->getSourceRange(), 3586bdd1243dSDimitry Andric std::to_string(NumArgs + 1)); 35870b57cec5SDimitry Andric return; 35880b57cec5SDimitry Andric } 3589bdd1243dSDimitry Andric } else { 3590bdd1243dSDimitry Andric // Inescapable GCC compatibility diagnostic. 3591bdd1243dSDimitry Andric S.Diag(D->getLocation(), diag::warn_gcc_requires_variadic_function) << AL; 3592bdd1243dSDimitry Andric if (FirstArg <= Idx) { 3593bdd1243dSDimitry Andric // Else, the function is not variadic, and FirstArg must be 0 or any 3594bdd1243dSDimitry Andric // parameter after the format parameter. We don't offer a fixit because 3595bdd1243dSDimitry Andric // there are too many possible good values. 35960b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) 35970b57cec5SDimitry Andric << AL << 3 << FirstArgExpr->getSourceRange(); 35980b57cec5SDimitry Andric return; 35990b57cec5SDimitry Andric } 3600bdd1243dSDimitry Andric } 3601bdd1243dSDimitry Andric } 36020b57cec5SDimitry Andric 3603a7dea167SDimitry Andric FormatAttr *NewAttr = S.mergeFormatAttr(D, AL, II, Idx, FirstArg); 36040b57cec5SDimitry Andric if (NewAttr) 36050b57cec5SDimitry Andric D->addAttr(NewAttr); 36060b57cec5SDimitry Andric } 36070b57cec5SDimitry Andric 36080b57cec5SDimitry Andric /// Handle __attribute__((callback(CalleeIdx, PayloadIdx0, ...))) attributes. 36090b57cec5SDimitry Andric static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 36100b57cec5SDimitry Andric // The index that identifies the callback callee is mandatory. 36110b57cec5SDimitry Andric if (AL.getNumArgs() == 0) { 36120b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_callback_attribute_no_callee) 36130b57cec5SDimitry Andric << AL.getRange(); 36140b57cec5SDimitry Andric return; 36150b57cec5SDimitry Andric } 36160b57cec5SDimitry Andric 36170b57cec5SDimitry Andric bool HasImplicitThisParam = isInstanceMethod(D); 36180b57cec5SDimitry Andric int32_t NumArgs = getFunctionOrMethodNumParams(D); 36190b57cec5SDimitry Andric 36200b57cec5SDimitry Andric FunctionDecl *FD = D->getAsFunction(); 36210b57cec5SDimitry Andric assert(FD && "Expected a function declaration!"); 36220b57cec5SDimitry Andric 36230b57cec5SDimitry Andric llvm::StringMap<int> NameIdxMapping; 36240b57cec5SDimitry Andric NameIdxMapping["__"] = -1; 36250b57cec5SDimitry Andric 36260b57cec5SDimitry Andric NameIdxMapping["this"] = 0; 36270b57cec5SDimitry Andric 36280b57cec5SDimitry Andric int Idx = 1; 36290b57cec5SDimitry Andric for (const ParmVarDecl *PVD : FD->parameters()) 36300b57cec5SDimitry Andric NameIdxMapping[PVD->getName()] = Idx++; 36310b57cec5SDimitry Andric 36320b57cec5SDimitry Andric auto UnknownName = NameIdxMapping.end(); 36330b57cec5SDimitry Andric 36340b57cec5SDimitry Andric SmallVector<int, 8> EncodingIndices; 36350b57cec5SDimitry Andric for (unsigned I = 0, E = AL.getNumArgs(); I < E; ++I) { 36360b57cec5SDimitry Andric SourceRange SR; 36370b57cec5SDimitry Andric int32_t ArgIdx; 36380b57cec5SDimitry Andric 36390b57cec5SDimitry Andric if (AL.isArgIdent(I)) { 36400b57cec5SDimitry Andric IdentifierLoc *IdLoc = AL.getArgAsIdent(I); 36410b57cec5SDimitry Andric auto It = NameIdxMapping.find(IdLoc->Ident->getName()); 36420b57cec5SDimitry Andric if (It == UnknownName) { 36430b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_callback_attribute_argument_unknown) 36440b57cec5SDimitry Andric << IdLoc->Ident << IdLoc->Loc; 36450b57cec5SDimitry Andric return; 36460b57cec5SDimitry Andric } 36470b57cec5SDimitry Andric 36480b57cec5SDimitry Andric SR = SourceRange(IdLoc->Loc); 36490b57cec5SDimitry Andric ArgIdx = It->second; 36500b57cec5SDimitry Andric } else if (AL.isArgExpr(I)) { 36510b57cec5SDimitry Andric Expr *IdxExpr = AL.getArgAsExpr(I); 36520b57cec5SDimitry Andric 36530b57cec5SDimitry Andric // If the expression is not parseable as an int32_t we have a problem. 36540fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, IdxExpr, (uint32_t &)ArgIdx, I + 1, 36550b57cec5SDimitry Andric false)) { 36560b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) 36570b57cec5SDimitry Andric << AL << (I + 1) << IdxExpr->getSourceRange(); 36580b57cec5SDimitry Andric return; 36590b57cec5SDimitry Andric } 36600b57cec5SDimitry Andric 36610b57cec5SDimitry Andric // Check oob, excluding the special values, 0 and -1. 36620b57cec5SDimitry Andric if (ArgIdx < -1 || ArgIdx > NumArgs) { 36630b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) 36640b57cec5SDimitry Andric << AL << (I + 1) << IdxExpr->getSourceRange(); 36650b57cec5SDimitry Andric return; 36660b57cec5SDimitry Andric } 36670b57cec5SDimitry Andric 36680b57cec5SDimitry Andric SR = IdxExpr->getSourceRange(); 36690b57cec5SDimitry Andric } else { 36700b57cec5SDimitry Andric llvm_unreachable("Unexpected ParsedAttr argument type!"); 36710b57cec5SDimitry Andric } 36720b57cec5SDimitry Andric 36730b57cec5SDimitry Andric if (ArgIdx == 0 && !HasImplicitThisParam) { 36740b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_callback_implicit_this_not_available) 36750b57cec5SDimitry Andric << (I + 1) << SR; 36760b57cec5SDimitry Andric return; 36770b57cec5SDimitry Andric } 36780b57cec5SDimitry Andric 36790b57cec5SDimitry Andric // Adjust for the case we do not have an implicit "this" parameter. In this 36800b57cec5SDimitry Andric // case we decrease all positive values by 1 to get LLVM argument indices. 36810b57cec5SDimitry Andric if (!HasImplicitThisParam && ArgIdx > 0) 36820b57cec5SDimitry Andric ArgIdx -= 1; 36830b57cec5SDimitry Andric 36840b57cec5SDimitry Andric EncodingIndices.push_back(ArgIdx); 36850b57cec5SDimitry Andric } 36860b57cec5SDimitry Andric 36870b57cec5SDimitry Andric int CalleeIdx = EncodingIndices.front(); 36880b57cec5SDimitry Andric // Check if the callee index is proper, thus not "this" and not "unknown". 36890b57cec5SDimitry Andric // This means the "CalleeIdx" has to be non-negative if "HasImplicitThisParam" 36900b57cec5SDimitry Andric // is false and positive if "HasImplicitThisParam" is true. 36910b57cec5SDimitry Andric if (CalleeIdx < (int)HasImplicitThisParam) { 36920b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_callback_attribute_invalid_callee) 36930b57cec5SDimitry Andric << AL.getRange(); 36940b57cec5SDimitry Andric return; 36950b57cec5SDimitry Andric } 36960b57cec5SDimitry Andric 36970b57cec5SDimitry Andric // Get the callee type, note the index adjustment as the AST doesn't contain 36980b57cec5SDimitry Andric // the this type (which the callee cannot reference anyway!). 36990b57cec5SDimitry Andric const Type *CalleeType = 37000b57cec5SDimitry Andric getFunctionOrMethodParamType(D, CalleeIdx - HasImplicitThisParam) 37010b57cec5SDimitry Andric .getTypePtr(); 37020b57cec5SDimitry Andric if (!CalleeType || !CalleeType->isFunctionPointerType()) { 37030b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type) 37040b57cec5SDimitry Andric << AL.getRange(); 37050b57cec5SDimitry Andric return; 37060b57cec5SDimitry Andric } 37070b57cec5SDimitry Andric 37080b57cec5SDimitry Andric const Type *CalleeFnType = 37090b57cec5SDimitry Andric CalleeType->getPointeeType()->getUnqualifiedDesugaredType(); 37100b57cec5SDimitry Andric 37110b57cec5SDimitry Andric // TODO: Check the type of the callee arguments. 37120b57cec5SDimitry Andric 37130b57cec5SDimitry Andric const auto *CalleeFnProtoType = dyn_cast<FunctionProtoType>(CalleeFnType); 37140b57cec5SDimitry Andric if (!CalleeFnProtoType) { 37150b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type) 37160b57cec5SDimitry Andric << AL.getRange(); 37170b57cec5SDimitry Andric return; 37180b57cec5SDimitry Andric } 37190b57cec5SDimitry Andric 37200b57cec5SDimitry Andric if (CalleeFnProtoType->getNumParams() > EncodingIndices.size() - 1) { 37210b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) 37220b57cec5SDimitry Andric << AL << (unsigned)(EncodingIndices.size() - 1); 37230b57cec5SDimitry Andric return; 37240b57cec5SDimitry Andric } 37250b57cec5SDimitry Andric 37260b57cec5SDimitry Andric if (CalleeFnProtoType->getNumParams() < EncodingIndices.size() - 1) { 37270b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) 37280b57cec5SDimitry Andric << AL << (unsigned)(EncodingIndices.size() - 1); 37290b57cec5SDimitry Andric return; 37300b57cec5SDimitry Andric } 37310b57cec5SDimitry Andric 37320b57cec5SDimitry Andric if (CalleeFnProtoType->isVariadic()) { 37330b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_callback_callee_is_variadic) << AL.getRange(); 37340b57cec5SDimitry Andric return; 37350b57cec5SDimitry Andric } 37360b57cec5SDimitry Andric 37370b57cec5SDimitry Andric // Do not allow multiple callback attributes. 37380b57cec5SDimitry Andric if (D->hasAttr<CallbackAttr>()) { 37390b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_callback_attribute_multiple) << AL.getRange(); 37400b57cec5SDimitry Andric return; 37410b57cec5SDimitry Andric } 37420b57cec5SDimitry Andric 37430b57cec5SDimitry Andric D->addAttr(::new (S.Context) CallbackAttr( 3744a7dea167SDimitry Andric S.Context, AL, EncodingIndices.data(), EncodingIndices.size())); 37450b57cec5SDimitry Andric } 37460b57cec5SDimitry Andric 3747e8d8bef9SDimitry Andric static bool isFunctionLike(const Type &T) { 3748e8d8bef9SDimitry Andric // Check for explicit function types. 3749e8d8bef9SDimitry Andric // 'called_once' is only supported in Objective-C and it has 3750e8d8bef9SDimitry Andric // function pointers and block pointers. 3751e8d8bef9SDimitry Andric return T.isFunctionPointerType() || T.isBlockPointerType(); 3752e8d8bef9SDimitry Andric } 3753e8d8bef9SDimitry Andric 3754e8d8bef9SDimitry Andric /// Handle 'called_once' attribute. 3755e8d8bef9SDimitry Andric static void handleCalledOnceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 3756e8d8bef9SDimitry Andric // 'called_once' only applies to parameters representing functions. 3757e8d8bef9SDimitry Andric QualType T = cast<ParmVarDecl>(D)->getType(); 3758e8d8bef9SDimitry Andric 3759e8d8bef9SDimitry Andric if (!isFunctionLike(*T)) { 3760e8d8bef9SDimitry Andric S.Diag(AL.getLoc(), diag::err_called_once_attribute_wrong_type); 3761e8d8bef9SDimitry Andric return; 3762e8d8bef9SDimitry Andric } 3763e8d8bef9SDimitry Andric 3764e8d8bef9SDimitry Andric D->addAttr(::new (S.Context) CalledOnceAttr(S.Context, AL)); 3765e8d8bef9SDimitry Andric } 3766e8d8bef9SDimitry Andric 37670b57cec5SDimitry Andric static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 37680b57cec5SDimitry Andric // Try to find the underlying union declaration. 37690b57cec5SDimitry Andric RecordDecl *RD = nullptr; 37700b57cec5SDimitry Andric const auto *TD = dyn_cast<TypedefNameDecl>(D); 37710b57cec5SDimitry Andric if (TD && TD->getUnderlyingType()->isUnionType()) 37720b57cec5SDimitry Andric RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); 37730b57cec5SDimitry Andric else 37740b57cec5SDimitry Andric RD = dyn_cast<RecordDecl>(D); 37750b57cec5SDimitry Andric 37760b57cec5SDimitry Andric if (!RD || !RD->isUnion()) { 377706c3fb27SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 377806c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() << ExpectedUnion; 37790b57cec5SDimitry Andric return; 37800b57cec5SDimitry Andric } 37810b57cec5SDimitry Andric 37820b57cec5SDimitry Andric if (!RD->isCompleteDefinition()) { 37830b57cec5SDimitry Andric if (!RD->isBeingDefined()) 37840b57cec5SDimitry Andric S.Diag(AL.getLoc(), 37850b57cec5SDimitry Andric diag::warn_transparent_union_attribute_not_definition); 37860b57cec5SDimitry Andric return; 37870b57cec5SDimitry Andric } 37880b57cec5SDimitry Andric 37890b57cec5SDimitry Andric RecordDecl::field_iterator Field = RD->field_begin(), 37900b57cec5SDimitry Andric FieldEnd = RD->field_end(); 37910b57cec5SDimitry Andric if (Field == FieldEnd) { 37920b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields); 37930b57cec5SDimitry Andric return; 37940b57cec5SDimitry Andric } 37950b57cec5SDimitry Andric 37960b57cec5SDimitry Andric FieldDecl *FirstField = *Field; 37970b57cec5SDimitry Andric QualType FirstType = FirstField->getType(); 37980b57cec5SDimitry Andric if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { 37990b57cec5SDimitry Andric S.Diag(FirstField->getLocation(), 38000b57cec5SDimitry Andric diag::warn_transparent_union_attribute_floating) 38010b57cec5SDimitry Andric << FirstType->isVectorType() << FirstType; 38020b57cec5SDimitry Andric return; 38030b57cec5SDimitry Andric } 38040b57cec5SDimitry Andric 38050b57cec5SDimitry Andric if (FirstType->isIncompleteType()) 38060b57cec5SDimitry Andric return; 38070b57cec5SDimitry Andric uint64_t FirstSize = S.Context.getTypeSize(FirstType); 38080b57cec5SDimitry Andric uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); 38090b57cec5SDimitry Andric for (; Field != FieldEnd; ++Field) { 38100b57cec5SDimitry Andric QualType FieldType = Field->getType(); 38110b57cec5SDimitry Andric if (FieldType->isIncompleteType()) 38120b57cec5SDimitry Andric return; 38130b57cec5SDimitry Andric // FIXME: this isn't fully correct; we also need to test whether the 38140b57cec5SDimitry Andric // members of the union would all have the same calling convention as the 38150b57cec5SDimitry Andric // first member of the union. Checking just the size and alignment isn't 38160b57cec5SDimitry Andric // sufficient (consider structs passed on the stack instead of in registers 38170b57cec5SDimitry Andric // as an example). 38180b57cec5SDimitry Andric if (S.Context.getTypeSize(FieldType) != FirstSize || 38190b57cec5SDimitry Andric S.Context.getTypeAlign(FieldType) > FirstAlign) { 38200b57cec5SDimitry Andric // Warn if we drop the attribute. 38210b57cec5SDimitry Andric bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; 38220b57cec5SDimitry Andric unsigned FieldBits = isSize ? S.Context.getTypeSize(FieldType) 38230b57cec5SDimitry Andric : S.Context.getTypeAlign(FieldType); 38240b57cec5SDimitry Andric S.Diag(Field->getLocation(), 38250b57cec5SDimitry Andric diag::warn_transparent_union_attribute_field_size_align) 3826e8d8bef9SDimitry Andric << isSize << *Field << FieldBits; 38270b57cec5SDimitry Andric unsigned FirstBits = isSize ? FirstSize : FirstAlign; 38280b57cec5SDimitry Andric S.Diag(FirstField->getLocation(), 38290b57cec5SDimitry Andric diag::note_transparent_union_first_field_size_align) 38300b57cec5SDimitry Andric << isSize << FirstBits; 38310b57cec5SDimitry Andric return; 38320b57cec5SDimitry Andric } 38330b57cec5SDimitry Andric } 38340b57cec5SDimitry Andric 3835a7dea167SDimitry Andric RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL)); 38360b57cec5SDimitry Andric } 38370b57cec5SDimitry Andric 3838e8d8bef9SDimitry Andric void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, 3839e8d8bef9SDimitry Andric StringRef Str, MutableArrayRef<Expr *> Args) { 3840e8d8bef9SDimitry Andric auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI); 384181ad6265SDimitry Andric if (ConstantFoldAttrArgs( 384281ad6265SDimitry Andric CI, MutableArrayRef<Expr *>(Attr->args_begin(), Attr->args_end()))) { 3843e8d8bef9SDimitry Andric D->addAttr(Attr); 3844e8d8bef9SDimitry Andric } 384581ad6265SDimitry Andric } 3846e8d8bef9SDimitry Andric 38470b57cec5SDimitry Andric static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 3848e8d8bef9SDimitry Andric // Make sure that there is a string literal as the annotation's first 38490b57cec5SDimitry Andric // argument. 38500b57cec5SDimitry Andric StringRef Str; 38510b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) 38520b57cec5SDimitry Andric return; 38530b57cec5SDimitry Andric 3854e8d8bef9SDimitry Andric llvm::SmallVector<Expr *, 4> Args; 3855e8d8bef9SDimitry Andric Args.reserve(AL.getNumArgs() - 1); 3856e8d8bef9SDimitry Andric for (unsigned Idx = 1; Idx < AL.getNumArgs(); Idx++) { 3857e8d8bef9SDimitry Andric assert(!AL.isArgIdent(Idx)); 3858e8d8bef9SDimitry Andric Args.push_back(AL.getArgAsExpr(Idx)); 38590b57cec5SDimitry Andric } 38600b57cec5SDimitry Andric 3861e8d8bef9SDimitry Andric S.AddAnnotationAttr(D, AL, Str, Args); 38620b57cec5SDimitry Andric } 38630b57cec5SDimitry Andric 38640b57cec5SDimitry Andric static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 3865a7dea167SDimitry Andric S.AddAlignValueAttr(D, AL, AL.getArgAsExpr(0)); 38660b57cec5SDimitry Andric } 38670b57cec5SDimitry Andric 3868a7dea167SDimitry Andric void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) { 3869a7dea167SDimitry Andric AlignValueAttr TmpAttr(Context, CI, E); 3870a7dea167SDimitry Andric SourceLocation AttrLoc = CI.getLoc(); 38710b57cec5SDimitry Andric 38720b57cec5SDimitry Andric QualType T; 38730b57cec5SDimitry Andric if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) 38740b57cec5SDimitry Andric T = TD->getUnderlyingType(); 38750b57cec5SDimitry Andric else if (const auto *VD = dyn_cast<ValueDecl>(D)) 38760b57cec5SDimitry Andric T = VD->getType(); 38770b57cec5SDimitry Andric else 38780b57cec5SDimitry Andric llvm_unreachable("Unknown decl type for align_value"); 38790b57cec5SDimitry Andric 38800b57cec5SDimitry Andric if (!T->isDependentType() && !T->isAnyPointerType() && 38810b57cec5SDimitry Andric !T->isReferenceType() && !T->isMemberPointerType()) { 38820b57cec5SDimitry Andric Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only) 38835ffd83dbSDimitry Andric << &TmpAttr << T << D->getSourceRange(); 38840b57cec5SDimitry Andric return; 38850b57cec5SDimitry Andric } 38860b57cec5SDimitry Andric 38870b57cec5SDimitry Andric if (!E->isValueDependent()) { 38880b57cec5SDimitry Andric llvm::APSInt Alignment; 3889e8d8bef9SDimitry Andric ExprResult ICE = VerifyIntegerConstantExpression( 3890e8d8bef9SDimitry Andric E, &Alignment, diag::err_align_value_attribute_argument_not_int); 38910b57cec5SDimitry Andric if (ICE.isInvalid()) 38920b57cec5SDimitry Andric return; 38930b57cec5SDimitry Andric 38940b57cec5SDimitry Andric if (!Alignment.isPowerOf2()) { 38950b57cec5SDimitry Andric Diag(AttrLoc, diag::err_alignment_not_power_of_two) 38960b57cec5SDimitry Andric << E->getSourceRange(); 38970b57cec5SDimitry Andric return; 38980b57cec5SDimitry Andric } 38990b57cec5SDimitry Andric 3900a7dea167SDimitry Andric D->addAttr(::new (Context) AlignValueAttr(Context, CI, ICE.get())); 39010b57cec5SDimitry Andric return; 39020b57cec5SDimitry Andric } 39030b57cec5SDimitry Andric 39040b57cec5SDimitry Andric // Save dependent expressions in the AST to be instantiated. 3905a7dea167SDimitry Andric D->addAttr(::new (Context) AlignValueAttr(Context, CI, E)); 39060b57cec5SDimitry Andric } 39070b57cec5SDimitry Andric 39080b57cec5SDimitry Andric static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 390906c3fb27SDimitry Andric if (AL.hasParsedType()) { 391006c3fb27SDimitry Andric const ParsedType &TypeArg = AL.getTypeArg(); 391106c3fb27SDimitry Andric TypeSourceInfo *TInfo; 391206c3fb27SDimitry Andric (void)S.GetTypeFromParser( 391306c3fb27SDimitry Andric ParsedType::getFromOpaquePtr(TypeArg.getAsOpaquePtr()), &TInfo); 391406c3fb27SDimitry Andric if (AL.isPackExpansion() && 391506c3fb27SDimitry Andric !TInfo->getType()->containsUnexpandedParameterPack()) { 391606c3fb27SDimitry Andric S.Diag(AL.getEllipsisLoc(), 391706c3fb27SDimitry Andric diag::err_pack_expansion_without_parameter_packs); 391806c3fb27SDimitry Andric return; 391906c3fb27SDimitry Andric } 392006c3fb27SDimitry Andric 392106c3fb27SDimitry Andric if (!AL.isPackExpansion() && 392206c3fb27SDimitry Andric S.DiagnoseUnexpandedParameterPack(TInfo->getTypeLoc().getBeginLoc(), 392306c3fb27SDimitry Andric TInfo, Sema::UPPC_Expression)) 392406c3fb27SDimitry Andric return; 392506c3fb27SDimitry Andric 392606c3fb27SDimitry Andric S.AddAlignedAttr(D, AL, TInfo, AL.isPackExpansion()); 392706c3fb27SDimitry Andric return; 392806c3fb27SDimitry Andric } 392906c3fb27SDimitry Andric 39300b57cec5SDimitry Andric // check the attribute arguments. 39310b57cec5SDimitry Andric if (AL.getNumArgs() > 1) { 39320b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; 39330b57cec5SDimitry Andric return; 39340b57cec5SDimitry Andric } 39350b57cec5SDimitry Andric 39360b57cec5SDimitry Andric if (AL.getNumArgs() == 0) { 3937a7dea167SDimitry Andric D->addAttr(::new (S.Context) AlignedAttr(S.Context, AL, true, nullptr)); 39380b57cec5SDimitry Andric return; 39390b57cec5SDimitry Andric } 39400b57cec5SDimitry Andric 39410b57cec5SDimitry Andric Expr *E = AL.getArgAsExpr(0); 39420b57cec5SDimitry Andric if (AL.isPackExpansion() && !E->containsUnexpandedParameterPack()) { 39430b57cec5SDimitry Andric S.Diag(AL.getEllipsisLoc(), 39440b57cec5SDimitry Andric diag::err_pack_expansion_without_parameter_packs); 39450b57cec5SDimitry Andric return; 39460b57cec5SDimitry Andric } 39470b57cec5SDimitry Andric 39480b57cec5SDimitry Andric if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) 39490b57cec5SDimitry Andric return; 39500b57cec5SDimitry Andric 3951a7dea167SDimitry Andric S.AddAlignedAttr(D, AL, E, AL.isPackExpansion()); 39520b57cec5SDimitry Andric } 39530b57cec5SDimitry Andric 395406c3fb27SDimitry Andric /// Perform checking of type validity 395506c3fb27SDimitry Andric /// 395606c3fb27SDimitry Andric /// C++11 [dcl.align]p1: 395706c3fb27SDimitry Andric /// An alignment-specifier may be applied to a variable or to a class 395806c3fb27SDimitry Andric /// data member, but it shall not be applied to a bit-field, a function 395906c3fb27SDimitry Andric /// parameter, the formal parameter of a catch clause, or a variable 396006c3fb27SDimitry Andric /// declared with the register storage class specifier. An 396106c3fb27SDimitry Andric /// alignment-specifier may also be applied to the declaration of a class 396206c3fb27SDimitry Andric /// or enumeration type. 396306c3fb27SDimitry Andric /// CWG 2354: 396406c3fb27SDimitry Andric /// CWG agreed to remove permission for alignas to be applied to 396506c3fb27SDimitry Andric /// enumerations. 396606c3fb27SDimitry Andric /// C11 6.7.5/2: 396706c3fb27SDimitry Andric /// An alignment attribute shall not be specified in a declaration of 396806c3fb27SDimitry Andric /// a typedef, or a bit-field, or a function, or a parameter, or an 396906c3fb27SDimitry Andric /// object declared with the register storage-class specifier. 397006c3fb27SDimitry Andric static bool validateAlignasAppliedType(Sema &S, Decl *D, 397106c3fb27SDimitry Andric const AlignedAttr &Attr, 397206c3fb27SDimitry Andric SourceLocation AttrLoc) { 39730b57cec5SDimitry Andric int DiagKind = -1; 39740b57cec5SDimitry Andric if (isa<ParmVarDecl>(D)) { 39750b57cec5SDimitry Andric DiagKind = 0; 39760b57cec5SDimitry Andric } else if (const auto *VD = dyn_cast<VarDecl>(D)) { 39770b57cec5SDimitry Andric if (VD->getStorageClass() == SC_Register) 39780b57cec5SDimitry Andric DiagKind = 1; 39790b57cec5SDimitry Andric if (VD->isExceptionVariable()) 39800b57cec5SDimitry Andric DiagKind = 2; 39810b57cec5SDimitry Andric } else if (const auto *FD = dyn_cast<FieldDecl>(D)) { 39820b57cec5SDimitry Andric if (FD->isBitField()) 39830b57cec5SDimitry Andric DiagKind = 3; 398481ad6265SDimitry Andric } else if (const auto *ED = dyn_cast<EnumDecl>(D)) { 398581ad6265SDimitry Andric if (ED->getLangOpts().CPlusPlus) 398681ad6265SDimitry Andric DiagKind = 4; 39870b57cec5SDimitry Andric } else if (!isa<TagDecl>(D)) { 398806c3fb27SDimitry Andric return S.Diag(AttrLoc, diag::err_attribute_wrong_decl_type) 398906c3fb27SDimitry Andric << &Attr << Attr.isRegularKeywordAttribute() 399006c3fb27SDimitry Andric << (Attr.isC11() ? ExpectedVariableOrField 39910b57cec5SDimitry Andric : ExpectedVariableFieldOrTag); 39920b57cec5SDimitry Andric } 39930b57cec5SDimitry Andric if (DiagKind != -1) { 399406c3fb27SDimitry Andric return S.Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type) 399506c3fb27SDimitry Andric << &Attr << DiagKind; 399606c3fb27SDimitry Andric } 399706c3fb27SDimitry Andric return false; 399806c3fb27SDimitry Andric } 399906c3fb27SDimitry Andric 400006c3fb27SDimitry Andric void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, 400106c3fb27SDimitry Andric bool IsPackExpansion) { 400206c3fb27SDimitry Andric AlignedAttr TmpAttr(Context, CI, true, E); 400306c3fb27SDimitry Andric SourceLocation AttrLoc = CI.getLoc(); 400406c3fb27SDimitry Andric 400506c3fb27SDimitry Andric // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. 400606c3fb27SDimitry Andric if (TmpAttr.isAlignas() && 400706c3fb27SDimitry Andric validateAlignasAppliedType(*this, D, TmpAttr, AttrLoc)) 40080b57cec5SDimitry Andric return; 40090b57cec5SDimitry Andric 40100b57cec5SDimitry Andric if (E->isValueDependent()) { 40110b57cec5SDimitry Andric // We can't support a dependent alignment on a non-dependent type, 40120b57cec5SDimitry Andric // because we have no way to model that a type is "alignment-dependent" 40130b57cec5SDimitry Andric // but not dependent in any other way. 40140b57cec5SDimitry Andric if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) { 40150b57cec5SDimitry Andric if (!TND->getUnderlyingType()->isDependentType()) { 40160b57cec5SDimitry Andric Diag(AttrLoc, diag::err_alignment_dependent_typedef_name) 40170b57cec5SDimitry Andric << E->getSourceRange(); 40180b57cec5SDimitry Andric return; 40190b57cec5SDimitry Andric } 40200b57cec5SDimitry Andric } 40210b57cec5SDimitry Andric 40220b57cec5SDimitry Andric // Save dependent expressions in the AST to be instantiated. 4023a7dea167SDimitry Andric AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, E); 40240b57cec5SDimitry Andric AA->setPackExpansion(IsPackExpansion); 40250b57cec5SDimitry Andric D->addAttr(AA); 40260b57cec5SDimitry Andric return; 40270b57cec5SDimitry Andric } 40280b57cec5SDimitry Andric 40290b57cec5SDimitry Andric // FIXME: Cache the number on the AL object? 40300b57cec5SDimitry Andric llvm::APSInt Alignment; 4031e8d8bef9SDimitry Andric ExprResult ICE = VerifyIntegerConstantExpression( 4032e8d8bef9SDimitry Andric E, &Alignment, diag::err_aligned_attribute_argument_not_int); 40330b57cec5SDimitry Andric if (ICE.isInvalid()) 40340b57cec5SDimitry Andric return; 40350b57cec5SDimitry Andric 403606c3fb27SDimitry Andric uint64_t MaximumAlignment = Sema::MaximumAlignment; 403706c3fb27SDimitry Andric if (Context.getTargetInfo().getTriple().isOSBinFormatCOFF()) 403806c3fb27SDimitry Andric MaximumAlignment = std::min(MaximumAlignment, uint64_t(8192)); 403906c3fb27SDimitry Andric if (Alignment > MaximumAlignment) { 404006c3fb27SDimitry Andric Diag(AttrLoc, diag::err_attribute_aligned_too_great) 404106c3fb27SDimitry Andric << MaximumAlignment << E->getSourceRange(); 404206c3fb27SDimitry Andric return; 404306c3fb27SDimitry Andric } 404406c3fb27SDimitry Andric 40450b57cec5SDimitry Andric uint64_t AlignVal = Alignment.getZExtValue(); 40460b57cec5SDimitry Andric // C++11 [dcl.align]p2: 40470b57cec5SDimitry Andric // -- if the constant expression evaluates to zero, the alignment 40480b57cec5SDimitry Andric // specifier shall have no effect 40490b57cec5SDimitry Andric // C11 6.7.5p6: 40500b57cec5SDimitry Andric // An alignment specification of zero has no effect. 40510b57cec5SDimitry Andric if (!(TmpAttr.isAlignas() && !Alignment)) { 40520b57cec5SDimitry Andric if (!llvm::isPowerOf2_64(AlignVal)) { 40530b57cec5SDimitry Andric Diag(AttrLoc, diag::err_alignment_not_power_of_two) 40540b57cec5SDimitry Andric << E->getSourceRange(); 40550b57cec5SDimitry Andric return; 40560b57cec5SDimitry Andric } 40570b57cec5SDimitry Andric } 40580b57cec5SDimitry Andric 4059349cc55cSDimitry Andric const auto *VD = dyn_cast<VarDecl>(D); 4060bdd1243dSDimitry Andric if (VD) { 40610b57cec5SDimitry Andric unsigned MaxTLSAlign = 40620b57cec5SDimitry Andric Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign()) 40630b57cec5SDimitry Andric .getQuantity(); 4064349cc55cSDimitry Andric if (MaxTLSAlign && AlignVal > MaxTLSAlign && 40650b57cec5SDimitry Andric VD->getTLSKind() != VarDecl::TLS_None) { 40660b57cec5SDimitry Andric Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum) 40670b57cec5SDimitry Andric << (unsigned)AlignVal << VD << MaxTLSAlign; 40680b57cec5SDimitry Andric return; 40690b57cec5SDimitry Andric } 40700b57cec5SDimitry Andric } 40710b57cec5SDimitry Andric 4072349cc55cSDimitry Andric // On AIX, an aligned attribute can not decrease the alignment when applied 4073349cc55cSDimitry Andric // to a variable declaration with vector type. 4074349cc55cSDimitry Andric if (VD && Context.getTargetInfo().getTriple().isOSAIX()) { 4075349cc55cSDimitry Andric const Type *Ty = VD->getType().getTypePtr(); 4076349cc55cSDimitry Andric if (Ty->isVectorType() && AlignVal < 16) { 4077349cc55cSDimitry Andric Diag(VD->getLocation(), diag::warn_aligned_attr_underaligned) 4078349cc55cSDimitry Andric << VD->getType() << 16; 4079349cc55cSDimitry Andric return; 4080349cc55cSDimitry Andric } 4081349cc55cSDimitry Andric } 4082349cc55cSDimitry Andric 4083a7dea167SDimitry Andric AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, ICE.get()); 40840b57cec5SDimitry Andric AA->setPackExpansion(IsPackExpansion); 408506c3fb27SDimitry Andric AA->setCachedAlignmentValue( 408606c3fb27SDimitry Andric static_cast<unsigned>(AlignVal * Context.getCharWidth())); 40870b57cec5SDimitry Andric D->addAttr(AA); 40880b57cec5SDimitry Andric } 40890b57cec5SDimitry Andric 4090a7dea167SDimitry Andric void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, 4091a7dea167SDimitry Andric TypeSourceInfo *TS, bool IsPackExpansion) { 409206c3fb27SDimitry Andric AlignedAttr TmpAttr(Context, CI, false, TS); 409306c3fb27SDimitry Andric SourceLocation AttrLoc = CI.getLoc(); 409406c3fb27SDimitry Andric 409506c3fb27SDimitry Andric // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. 409606c3fb27SDimitry Andric if (TmpAttr.isAlignas() && 409706c3fb27SDimitry Andric validateAlignasAppliedType(*this, D, TmpAttr, AttrLoc)) 409806c3fb27SDimitry Andric return; 409906c3fb27SDimitry Andric 410006c3fb27SDimitry Andric if (TS->getType()->isDependentType()) { 410106c3fb27SDimitry Andric // We can't support a dependent alignment on a non-dependent type, 410206c3fb27SDimitry Andric // because we have no way to model that a type is "type-dependent" 410306c3fb27SDimitry Andric // but not dependent in any other way. 410406c3fb27SDimitry Andric if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) { 410506c3fb27SDimitry Andric if (!TND->getUnderlyingType()->isDependentType()) { 410606c3fb27SDimitry Andric Diag(AttrLoc, diag::err_alignment_dependent_typedef_name) 410706c3fb27SDimitry Andric << TS->getTypeLoc().getSourceRange(); 410806c3fb27SDimitry Andric return; 410906c3fb27SDimitry Andric } 411006c3fb27SDimitry Andric } 411106c3fb27SDimitry Andric 4112a7dea167SDimitry Andric AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, false, TS); 41130b57cec5SDimitry Andric AA->setPackExpansion(IsPackExpansion); 41140b57cec5SDimitry Andric D->addAttr(AA); 411506c3fb27SDimitry Andric return; 411606c3fb27SDimitry Andric } 411706c3fb27SDimitry Andric 411806c3fb27SDimitry Andric const auto *VD = dyn_cast<VarDecl>(D); 411906c3fb27SDimitry Andric unsigned AlignVal = TmpAttr.getAlignment(Context); 412006c3fb27SDimitry Andric // On AIX, an aligned attribute can not decrease the alignment when applied 412106c3fb27SDimitry Andric // to a variable declaration with vector type. 412206c3fb27SDimitry Andric if (VD && Context.getTargetInfo().getTriple().isOSAIX()) { 412306c3fb27SDimitry Andric const Type *Ty = VD->getType().getTypePtr(); 412406c3fb27SDimitry Andric if (Ty->isVectorType() && 412506c3fb27SDimitry Andric Context.toCharUnitsFromBits(AlignVal).getQuantity() < 16) { 412606c3fb27SDimitry Andric Diag(VD->getLocation(), diag::warn_aligned_attr_underaligned) 412706c3fb27SDimitry Andric << VD->getType() << 16; 412806c3fb27SDimitry Andric return; 412906c3fb27SDimitry Andric } 413006c3fb27SDimitry Andric } 413106c3fb27SDimitry Andric 413206c3fb27SDimitry Andric AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, false, TS); 413306c3fb27SDimitry Andric AA->setPackExpansion(IsPackExpansion); 413406c3fb27SDimitry Andric AA->setCachedAlignmentValue(AlignVal); 413506c3fb27SDimitry Andric D->addAttr(AA); 41360b57cec5SDimitry Andric } 41370b57cec5SDimitry Andric 41380b57cec5SDimitry Andric void Sema::CheckAlignasUnderalignment(Decl *D) { 41390b57cec5SDimitry Andric assert(D->hasAttrs() && "no attributes on decl"); 41400b57cec5SDimitry Andric 41410b57cec5SDimitry Andric QualType UnderlyingTy, DiagTy; 41420b57cec5SDimitry Andric if (const auto *VD = dyn_cast<ValueDecl>(D)) { 41430b57cec5SDimitry Andric UnderlyingTy = DiagTy = VD->getType(); 41440b57cec5SDimitry Andric } else { 41450b57cec5SDimitry Andric UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D)); 41460b57cec5SDimitry Andric if (const auto *ED = dyn_cast<EnumDecl>(D)) 41470b57cec5SDimitry Andric UnderlyingTy = ED->getIntegerType(); 41480b57cec5SDimitry Andric } 41490b57cec5SDimitry Andric if (DiagTy->isDependentType() || DiagTy->isIncompleteType()) 41500b57cec5SDimitry Andric return; 41510b57cec5SDimitry Andric 41520b57cec5SDimitry Andric // C++11 [dcl.align]p5, C11 6.7.5/4: 41530b57cec5SDimitry Andric // The combined effect of all alignment attributes in a declaration shall 41540b57cec5SDimitry Andric // not specify an alignment that is less strict than the alignment that 41550b57cec5SDimitry Andric // would otherwise be required for the entity being declared. 41560b57cec5SDimitry Andric AlignedAttr *AlignasAttr = nullptr; 41575ffd83dbSDimitry Andric AlignedAttr *LastAlignedAttr = nullptr; 41580b57cec5SDimitry Andric unsigned Align = 0; 41590b57cec5SDimitry Andric for (auto *I : D->specific_attrs<AlignedAttr>()) { 41600b57cec5SDimitry Andric if (I->isAlignmentDependent()) 41610b57cec5SDimitry Andric return; 41620b57cec5SDimitry Andric if (I->isAlignas()) 41630b57cec5SDimitry Andric AlignasAttr = I; 41640b57cec5SDimitry Andric Align = std::max(Align, I->getAlignment(Context)); 41655ffd83dbSDimitry Andric LastAlignedAttr = I; 41660b57cec5SDimitry Andric } 41670b57cec5SDimitry Andric 41685ffd83dbSDimitry Andric if (Align && DiagTy->isSizelessType()) { 41695ffd83dbSDimitry Andric Diag(LastAlignedAttr->getLocation(), diag::err_attribute_sizeless_type) 41705ffd83dbSDimitry Andric << LastAlignedAttr << DiagTy; 41715ffd83dbSDimitry Andric } else if (AlignasAttr && Align) { 41720b57cec5SDimitry Andric CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); 41730b57cec5SDimitry Andric CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy); 41740b57cec5SDimitry Andric if (NaturalAlign > RequestedAlign) 41750b57cec5SDimitry Andric Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) 41760b57cec5SDimitry Andric << DiagTy << (unsigned)NaturalAlign.getQuantity(); 41770b57cec5SDimitry Andric } 41780b57cec5SDimitry Andric } 41790b57cec5SDimitry Andric 41800b57cec5SDimitry Andric bool Sema::checkMSInheritanceAttrOnDefinition( 41810b57cec5SDimitry Andric CXXRecordDecl *RD, SourceRange Range, bool BestCase, 4182480093f4SDimitry Andric MSInheritanceModel ExplicitModel) { 41830b57cec5SDimitry Andric assert(RD->hasDefinition() && "RD has no definition!"); 41840b57cec5SDimitry Andric 41850b57cec5SDimitry Andric // We may not have seen base specifiers or any virtual methods yet. We will 41860b57cec5SDimitry Andric // have to wait until the record is defined to catch any mismatches. 41870b57cec5SDimitry Andric if (!RD->getDefinition()->isCompleteDefinition()) 41880b57cec5SDimitry Andric return false; 41890b57cec5SDimitry Andric 41900b57cec5SDimitry Andric // The unspecified model never matches what a definition could need. 4191480093f4SDimitry Andric if (ExplicitModel == MSInheritanceModel::Unspecified) 41920b57cec5SDimitry Andric return false; 41930b57cec5SDimitry Andric 41940b57cec5SDimitry Andric if (BestCase) { 4195480093f4SDimitry Andric if (RD->calculateInheritanceModel() == ExplicitModel) 41960b57cec5SDimitry Andric return false; 41970b57cec5SDimitry Andric } else { 4198480093f4SDimitry Andric if (RD->calculateInheritanceModel() <= ExplicitModel) 41990b57cec5SDimitry Andric return false; 42000b57cec5SDimitry Andric } 42010b57cec5SDimitry Andric 42020b57cec5SDimitry Andric Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance) 42030b57cec5SDimitry Andric << 0 /*definition*/; 42045ffd83dbSDimitry Andric Diag(RD->getDefinition()->getLocation(), diag::note_defined_here) << RD; 42050b57cec5SDimitry Andric return true; 42060b57cec5SDimitry Andric } 42070b57cec5SDimitry Andric 42080b57cec5SDimitry Andric /// parseModeAttrArg - Parses attribute mode string and returns parsed type 42090b57cec5SDimitry Andric /// attribute. 42100b57cec5SDimitry Andric static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, 42115ffd83dbSDimitry Andric bool &IntegerMode, bool &ComplexMode, 4212349cc55cSDimitry Andric FloatModeKind &ExplicitType) { 42130b57cec5SDimitry Andric IntegerMode = true; 42140b57cec5SDimitry Andric ComplexMode = false; 4215349cc55cSDimitry Andric ExplicitType = FloatModeKind::NoFloat; 42160b57cec5SDimitry Andric switch (Str.size()) { 42170b57cec5SDimitry Andric case 2: 42180b57cec5SDimitry Andric switch (Str[0]) { 42190b57cec5SDimitry Andric case 'Q': 42200b57cec5SDimitry Andric DestWidth = 8; 42210b57cec5SDimitry Andric break; 42220b57cec5SDimitry Andric case 'H': 42230b57cec5SDimitry Andric DestWidth = 16; 42240b57cec5SDimitry Andric break; 42250b57cec5SDimitry Andric case 'S': 42260b57cec5SDimitry Andric DestWidth = 32; 42270b57cec5SDimitry Andric break; 42280b57cec5SDimitry Andric case 'D': 42290b57cec5SDimitry Andric DestWidth = 64; 42300b57cec5SDimitry Andric break; 42310b57cec5SDimitry Andric case 'X': 42320b57cec5SDimitry Andric DestWidth = 96; 42330b57cec5SDimitry Andric break; 42345ffd83dbSDimitry Andric case 'K': // KFmode - IEEE quad precision (__float128) 4235349cc55cSDimitry Andric ExplicitType = FloatModeKind::Float128; 42365ffd83dbSDimitry Andric DestWidth = Str[1] == 'I' ? 0 : 128; 42375ffd83dbSDimitry Andric break; 42380b57cec5SDimitry Andric case 'T': 4239349cc55cSDimitry Andric ExplicitType = FloatModeKind::LongDouble; 42400b57cec5SDimitry Andric DestWidth = 128; 42410b57cec5SDimitry Andric break; 4242349cc55cSDimitry Andric case 'I': 4243349cc55cSDimitry Andric ExplicitType = FloatModeKind::Ibm128; 4244349cc55cSDimitry Andric DestWidth = Str[1] == 'I' ? 0 : 128; 4245349cc55cSDimitry Andric break; 42460b57cec5SDimitry Andric } 42470b57cec5SDimitry Andric if (Str[1] == 'F') { 42480b57cec5SDimitry Andric IntegerMode = false; 42490b57cec5SDimitry Andric } else if (Str[1] == 'C') { 42500b57cec5SDimitry Andric IntegerMode = false; 42510b57cec5SDimitry Andric ComplexMode = true; 42520b57cec5SDimitry Andric } else if (Str[1] != 'I') { 42530b57cec5SDimitry Andric DestWidth = 0; 42540b57cec5SDimitry Andric } 42550b57cec5SDimitry Andric break; 42560b57cec5SDimitry Andric case 4: 42570b57cec5SDimitry Andric // FIXME: glibc uses 'word' to define register_t; this is narrower than a 42580b57cec5SDimitry Andric // pointer on PIC16 and other embedded platforms. 42590b57cec5SDimitry Andric if (Str == "word") 42600b57cec5SDimitry Andric DestWidth = S.Context.getTargetInfo().getRegisterWidth(); 42610b57cec5SDimitry Andric else if (Str == "byte") 42620b57cec5SDimitry Andric DestWidth = S.Context.getTargetInfo().getCharWidth(); 42630b57cec5SDimitry Andric break; 42640b57cec5SDimitry Andric case 7: 42650b57cec5SDimitry Andric if (Str == "pointer") 4266bdd1243dSDimitry Andric DestWidth = S.Context.getTargetInfo().getPointerWidth(LangAS::Default); 42670b57cec5SDimitry Andric break; 42680b57cec5SDimitry Andric case 11: 42690b57cec5SDimitry Andric if (Str == "unwind_word") 42700b57cec5SDimitry Andric DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); 42710b57cec5SDimitry Andric break; 42720b57cec5SDimitry Andric } 42730b57cec5SDimitry Andric } 42740b57cec5SDimitry Andric 42750b57cec5SDimitry Andric /// handleModeAttr - This attribute modifies the width of a decl with primitive 42760b57cec5SDimitry Andric /// type. 42770b57cec5SDimitry Andric /// 42780b57cec5SDimitry Andric /// Despite what would be logical, the mode attribute is a decl attribute, not a 42790b57cec5SDimitry Andric /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be 42800b57cec5SDimitry Andric /// HImode, not an intermediate pointer. 42810b57cec5SDimitry Andric static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 42820b57cec5SDimitry Andric // This attribute isn't documented, but glibc uses it. It changes 42830b57cec5SDimitry Andric // the width of an int or unsigned int to the specified size. 42840b57cec5SDimitry Andric if (!AL.isArgIdent(0)) { 42850b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 42860b57cec5SDimitry Andric << AL << AANT_ArgumentIdentifier; 42870b57cec5SDimitry Andric return; 42880b57cec5SDimitry Andric } 42890b57cec5SDimitry Andric 42900b57cec5SDimitry Andric IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident; 42910b57cec5SDimitry Andric 4292a7dea167SDimitry Andric S.AddModeAttr(D, AL, Name); 42930b57cec5SDimitry Andric } 42940b57cec5SDimitry Andric 4295a7dea167SDimitry Andric void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI, 4296a7dea167SDimitry Andric IdentifierInfo *Name, bool InInstantiation) { 42970b57cec5SDimitry Andric StringRef Str = Name->getName(); 42980b57cec5SDimitry Andric normalizeName(Str); 4299a7dea167SDimitry Andric SourceLocation AttrLoc = CI.getLoc(); 43000b57cec5SDimitry Andric 43010b57cec5SDimitry Andric unsigned DestWidth = 0; 43020b57cec5SDimitry Andric bool IntegerMode = true; 43030b57cec5SDimitry Andric bool ComplexMode = false; 4304349cc55cSDimitry Andric FloatModeKind ExplicitType = FloatModeKind::NoFloat; 43050b57cec5SDimitry Andric llvm::APInt VectorSize(64, 0); 43060b57cec5SDimitry Andric if (Str.size() >= 4 && Str[0] == 'V') { 43070b57cec5SDimitry Andric // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2). 43080b57cec5SDimitry Andric size_t StrSize = Str.size(); 43090b57cec5SDimitry Andric size_t VectorStringLength = 0; 43100b57cec5SDimitry Andric while ((VectorStringLength + 1) < StrSize && 43110b57cec5SDimitry Andric isdigit(Str[VectorStringLength + 1])) 43120b57cec5SDimitry Andric ++VectorStringLength; 43130b57cec5SDimitry Andric if (VectorStringLength && 43140b57cec5SDimitry Andric !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && 43150b57cec5SDimitry Andric VectorSize.isPowerOf2()) { 43160b57cec5SDimitry Andric parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth, 4317349cc55cSDimitry Andric IntegerMode, ComplexMode, ExplicitType); 43180b57cec5SDimitry Andric // Avoid duplicate warning from template instantiation. 43190b57cec5SDimitry Andric if (!InInstantiation) 43200b57cec5SDimitry Andric Diag(AttrLoc, diag::warn_vector_mode_deprecated); 43210b57cec5SDimitry Andric } else { 43220b57cec5SDimitry Andric VectorSize = 0; 43230b57cec5SDimitry Andric } 43240b57cec5SDimitry Andric } 43250b57cec5SDimitry Andric 43260b57cec5SDimitry Andric if (!VectorSize) 43275ffd83dbSDimitry Andric parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode, 4328349cc55cSDimitry Andric ExplicitType); 43290b57cec5SDimitry Andric 43300b57cec5SDimitry Andric // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t 43310b57cec5SDimitry Andric // and friends, at least with glibc. 43320b57cec5SDimitry Andric // FIXME: Make sure floating-point mappings are accurate 43330b57cec5SDimitry Andric // FIXME: Support XF and TF types 43340b57cec5SDimitry Andric if (!DestWidth) { 43350b57cec5SDimitry Andric Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name; 43360b57cec5SDimitry Andric return; 43370b57cec5SDimitry Andric } 43380b57cec5SDimitry Andric 43390b57cec5SDimitry Andric QualType OldTy; 43400b57cec5SDimitry Andric if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) 43410b57cec5SDimitry Andric OldTy = TD->getUnderlyingType(); 43420b57cec5SDimitry Andric else if (const auto *ED = dyn_cast<EnumDecl>(D)) { 43430b57cec5SDimitry Andric // Something like 'typedef enum { X } __attribute__((mode(XX))) T;'. 43440b57cec5SDimitry Andric // Try to get type from enum declaration, default to int. 43450b57cec5SDimitry Andric OldTy = ED->getIntegerType(); 43460b57cec5SDimitry Andric if (OldTy.isNull()) 43470b57cec5SDimitry Andric OldTy = Context.IntTy; 43480b57cec5SDimitry Andric } else 43490b57cec5SDimitry Andric OldTy = cast<ValueDecl>(D)->getType(); 43500b57cec5SDimitry Andric 43510b57cec5SDimitry Andric if (OldTy->isDependentType()) { 4352a7dea167SDimitry Andric D->addAttr(::new (Context) ModeAttr(Context, CI, Name)); 43530b57cec5SDimitry Andric return; 43540b57cec5SDimitry Andric } 43550b57cec5SDimitry Andric 43560b57cec5SDimitry Andric // Base type can also be a vector type (see PR17453). 43570b57cec5SDimitry Andric // Distinguish between base type and base element type. 43580b57cec5SDimitry Andric QualType OldElemTy = OldTy; 43590b57cec5SDimitry Andric if (const auto *VT = OldTy->getAs<VectorType>()) 43600b57cec5SDimitry Andric OldElemTy = VT->getElementType(); 43610b57cec5SDimitry Andric 43620b57cec5SDimitry Andric // GCC allows 'mode' attribute on enumeration types (even incomplete), except 43630b57cec5SDimitry Andric // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete 43640b57cec5SDimitry Andric // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected. 43650b57cec5SDimitry Andric if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) && 43660b57cec5SDimitry Andric VectorSize.getBoolValue()) { 4367a7dea167SDimitry Andric Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << CI.getRange(); 43680b57cec5SDimitry Andric return; 43690b57cec5SDimitry Andric } 43705ffd83dbSDimitry Andric bool IntegralOrAnyEnumType = (OldElemTy->isIntegralOrEnumerationType() && 43710eae32dcSDimitry Andric !OldElemTy->isBitIntType()) || 43725ffd83dbSDimitry Andric OldElemTy->getAs<EnumType>(); 43730b57cec5SDimitry Andric 43740b57cec5SDimitry Andric if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() && 43750b57cec5SDimitry Andric !IntegralOrAnyEnumType) 43760b57cec5SDimitry Andric Diag(AttrLoc, diag::err_mode_not_primitive); 43770b57cec5SDimitry Andric else if (IntegerMode) { 43780b57cec5SDimitry Andric if (!IntegralOrAnyEnumType) 43790b57cec5SDimitry Andric Diag(AttrLoc, diag::err_mode_wrong_type); 43800b57cec5SDimitry Andric } else if (ComplexMode) { 43810b57cec5SDimitry Andric if (!OldElemTy->isComplexType()) 43820b57cec5SDimitry Andric Diag(AttrLoc, diag::err_mode_wrong_type); 43830b57cec5SDimitry Andric } else { 43840b57cec5SDimitry Andric if (!OldElemTy->isFloatingType()) 43850b57cec5SDimitry Andric Diag(AttrLoc, diag::err_mode_wrong_type); 43860b57cec5SDimitry Andric } 43870b57cec5SDimitry Andric 43880b57cec5SDimitry Andric QualType NewElemTy; 43890b57cec5SDimitry Andric 43900b57cec5SDimitry Andric if (IntegerMode) 43910b57cec5SDimitry Andric NewElemTy = Context.getIntTypeForBitwidth(DestWidth, 43920b57cec5SDimitry Andric OldElemTy->isSignedIntegerType()); 43930b57cec5SDimitry Andric else 4394349cc55cSDimitry Andric NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitType); 43950b57cec5SDimitry Andric 43960b57cec5SDimitry Andric if (NewElemTy.isNull()) { 43970fca6ea1SDimitry Andric // Only emit diagnostic on host for 128-bit mode attribute 43980fca6ea1SDimitry Andric if (!(DestWidth == 128 && getLangOpts().CUDAIsDevice)) 43990b57cec5SDimitry Andric Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name; 44000b57cec5SDimitry Andric return; 44010b57cec5SDimitry Andric } 44020b57cec5SDimitry Andric 44030b57cec5SDimitry Andric if (ComplexMode) { 44040b57cec5SDimitry Andric NewElemTy = Context.getComplexType(NewElemTy); 44050b57cec5SDimitry Andric } 44060b57cec5SDimitry Andric 44070b57cec5SDimitry Andric QualType NewTy = NewElemTy; 44080b57cec5SDimitry Andric if (VectorSize.getBoolValue()) { 44090b57cec5SDimitry Andric NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(), 44105f757f3fSDimitry Andric VectorKind::Generic); 44110b57cec5SDimitry Andric } else if (const auto *OldVT = OldTy->getAs<VectorType>()) { 44120b57cec5SDimitry Andric // Complex machine mode does not support base vector types. 44130b57cec5SDimitry Andric if (ComplexMode) { 44140b57cec5SDimitry Andric Diag(AttrLoc, diag::err_complex_mode_vector_type); 44150b57cec5SDimitry Andric return; 44160b57cec5SDimitry Andric } 44170b57cec5SDimitry Andric unsigned NumElements = Context.getTypeSize(OldElemTy) * 44180b57cec5SDimitry Andric OldVT->getNumElements() / 44190b57cec5SDimitry Andric Context.getTypeSize(NewElemTy); 44200b57cec5SDimitry Andric NewTy = 44210b57cec5SDimitry Andric Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind()); 44220b57cec5SDimitry Andric } 44230b57cec5SDimitry Andric 44240b57cec5SDimitry Andric if (NewTy.isNull()) { 44250b57cec5SDimitry Andric Diag(AttrLoc, diag::err_mode_wrong_type); 44260b57cec5SDimitry Andric return; 44270b57cec5SDimitry Andric } 44280b57cec5SDimitry Andric 44290b57cec5SDimitry Andric // Install the new type. 44300b57cec5SDimitry Andric if (auto *TD = dyn_cast<TypedefNameDecl>(D)) 44310b57cec5SDimitry Andric TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); 44320b57cec5SDimitry Andric else if (auto *ED = dyn_cast<EnumDecl>(D)) 44330b57cec5SDimitry Andric ED->setIntegerType(NewTy); 44340b57cec5SDimitry Andric else 44350b57cec5SDimitry Andric cast<ValueDecl>(D)->setType(NewTy); 44360b57cec5SDimitry Andric 4437a7dea167SDimitry Andric D->addAttr(::new (Context) ModeAttr(Context, CI, Name)); 44380b57cec5SDimitry Andric } 44390b57cec5SDimitry Andric 44400b57cec5SDimitry Andric static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4441a7dea167SDimitry Andric D->addAttr(::new (S.Context) NoDebugAttr(S.Context, AL)); 44420b57cec5SDimitry Andric } 44430b57cec5SDimitry Andric 4444a7dea167SDimitry Andric AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, 4445a7dea167SDimitry Andric const AttributeCommonInfo &CI, 4446a7dea167SDimitry Andric const IdentifierInfo *Ident) { 44470b57cec5SDimitry Andric if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) { 4448a7dea167SDimitry Andric Diag(CI.getLoc(), diag::warn_attribute_ignored) << Ident; 44490b57cec5SDimitry Andric Diag(Optnone->getLocation(), diag::note_conflicting_attribute); 44500b57cec5SDimitry Andric return nullptr; 44510b57cec5SDimitry Andric } 44520b57cec5SDimitry Andric 44530b57cec5SDimitry Andric if (D->hasAttr<AlwaysInlineAttr>()) 44540b57cec5SDimitry Andric return nullptr; 44550b57cec5SDimitry Andric 4456a7dea167SDimitry Andric return ::new (Context) AlwaysInlineAttr(Context, CI); 44570b57cec5SDimitry Andric } 44580b57cec5SDimitry Andric 44590b57cec5SDimitry Andric InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D, 44600b57cec5SDimitry Andric const ParsedAttr &AL) { 44610b57cec5SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D)) { 44620b57cec5SDimitry Andric // Attribute applies to Var but not any subclass of it (like ParmVar, 44630b57cec5SDimitry Andric // ImplicitParm or VarTemplateSpecialization). 44640b57cec5SDimitry Andric if (VD->getKind() != Decl::Var) { 44650b57cec5SDimitry Andric Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 446606c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() 446706c3fb27SDimitry Andric << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass 44680b57cec5SDimitry Andric : ExpectedVariableOrFunction); 44690b57cec5SDimitry Andric return nullptr; 44700b57cec5SDimitry Andric } 44710b57cec5SDimitry Andric // Attribute does not apply to non-static local variables. 44720b57cec5SDimitry Andric if (VD->hasLocalStorage()) { 44730b57cec5SDimitry Andric Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); 44740b57cec5SDimitry Andric return nullptr; 44750b57cec5SDimitry Andric } 44760b57cec5SDimitry Andric } 44770b57cec5SDimitry Andric 4478a7dea167SDimitry Andric return ::new (Context) InternalLinkageAttr(Context, AL); 44790b57cec5SDimitry Andric } 44800b57cec5SDimitry Andric InternalLinkageAttr * 44810b57cec5SDimitry Andric Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) { 44820b57cec5SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D)) { 44830b57cec5SDimitry Andric // Attribute applies to Var but not any subclass of it (like ParmVar, 44840b57cec5SDimitry Andric // ImplicitParm or VarTemplateSpecialization). 44850b57cec5SDimitry Andric if (VD->getKind() != Decl::Var) { 44860b57cec5SDimitry Andric Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type) 448706c3fb27SDimitry Andric << &AL << AL.isRegularKeywordAttribute() 448806c3fb27SDimitry Andric << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass 44890b57cec5SDimitry Andric : ExpectedVariableOrFunction); 44900b57cec5SDimitry Andric return nullptr; 44910b57cec5SDimitry Andric } 44920b57cec5SDimitry Andric // Attribute does not apply to non-static local variables. 44930b57cec5SDimitry Andric if (VD->hasLocalStorage()) { 44940b57cec5SDimitry Andric Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); 44950b57cec5SDimitry Andric return nullptr; 44960b57cec5SDimitry Andric } 44970b57cec5SDimitry Andric } 44980b57cec5SDimitry Andric 4499a7dea167SDimitry Andric return ::new (Context) InternalLinkageAttr(Context, AL); 45000b57cec5SDimitry Andric } 45010b57cec5SDimitry Andric 4502a7dea167SDimitry Andric MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI) { 45030b57cec5SDimitry Andric if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) { 4504a7dea167SDimitry Andric Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'minsize'"; 45050b57cec5SDimitry Andric Diag(Optnone->getLocation(), diag::note_conflicting_attribute); 45060b57cec5SDimitry Andric return nullptr; 45070b57cec5SDimitry Andric } 45080b57cec5SDimitry Andric 45090b57cec5SDimitry Andric if (D->hasAttr<MinSizeAttr>()) 45100b57cec5SDimitry Andric return nullptr; 45110b57cec5SDimitry Andric 4512a7dea167SDimitry Andric return ::new (Context) MinSizeAttr(Context, CI); 45130b57cec5SDimitry Andric } 45140b57cec5SDimitry Andric 4515a7dea167SDimitry Andric OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, 4516a7dea167SDimitry Andric const AttributeCommonInfo &CI) { 45170b57cec5SDimitry Andric if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) { 45180b57cec5SDimitry Andric Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline; 4519a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_conflicting_attribute); 45200b57cec5SDimitry Andric D->dropAttr<AlwaysInlineAttr>(); 45210b57cec5SDimitry Andric } 45220b57cec5SDimitry Andric if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) { 45230b57cec5SDimitry Andric Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize; 4524a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_conflicting_attribute); 45250b57cec5SDimitry Andric D->dropAttr<MinSizeAttr>(); 45260b57cec5SDimitry Andric } 45270b57cec5SDimitry Andric 45280b57cec5SDimitry Andric if (D->hasAttr<OptimizeNoneAttr>()) 45290b57cec5SDimitry Andric return nullptr; 45300b57cec5SDimitry Andric 4531a7dea167SDimitry Andric return ::new (Context) OptimizeNoneAttr(Context, CI); 45320b57cec5SDimitry Andric } 45330b57cec5SDimitry Andric 45340b57cec5SDimitry Andric static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4535a7dea167SDimitry Andric if (AlwaysInlineAttr *Inline = 4536a7dea167SDimitry Andric S.mergeAlwaysInlineAttr(D, AL, AL.getAttrName())) 45370b57cec5SDimitry Andric D->addAttr(Inline); 45380b57cec5SDimitry Andric } 45390b57cec5SDimitry Andric 45400b57cec5SDimitry Andric static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4541a7dea167SDimitry Andric if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(D, AL)) 45420b57cec5SDimitry Andric D->addAttr(MinSize); 45430b57cec5SDimitry Andric } 45440b57cec5SDimitry Andric 45450b57cec5SDimitry Andric static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4546a7dea167SDimitry Andric if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(D, AL)) 45470b57cec5SDimitry Andric D->addAttr(Optnone); 45480b57cec5SDimitry Andric } 45490b57cec5SDimitry Andric 45500b57cec5SDimitry Andric static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 45510b57cec5SDimitry Andric const auto *VD = cast<VarDecl>(D); 4552e8d8bef9SDimitry Andric if (VD->hasLocalStorage()) { 4553e8d8bef9SDimitry Andric S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); 45540b57cec5SDimitry Andric return; 45550b57cec5SDimitry Andric } 4556fe6060f1SDimitry Andric // constexpr variable may already get an implicit constant attr, which should 4557fe6060f1SDimitry Andric // be replaced by the explicit constant attr. 4558fe6060f1SDimitry Andric if (auto *A = D->getAttr<CUDAConstantAttr>()) { 4559fe6060f1SDimitry Andric if (!A->isImplicit()) 4560fe6060f1SDimitry Andric return; 4561fe6060f1SDimitry Andric D->dropAttr<CUDAConstantAttr>(); 4562fe6060f1SDimitry Andric } 4563a7dea167SDimitry Andric D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL)); 45640b57cec5SDimitry Andric } 45650b57cec5SDimitry Andric 45660b57cec5SDimitry Andric static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 45670b57cec5SDimitry Andric const auto *VD = cast<VarDecl>(D); 45680b57cec5SDimitry Andric // extern __shared__ is only allowed on arrays with no length (e.g. 45690b57cec5SDimitry Andric // "int x[]"). 45700b57cec5SDimitry Andric if (!S.getLangOpts().GPURelocatableDeviceCode && VD->hasExternalStorage() && 45710b57cec5SDimitry Andric !isa<IncompleteArrayType>(VD->getType())) { 45720b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD; 45730b57cec5SDimitry Andric return; 45740b57cec5SDimitry Andric } 45750b57cec5SDimitry Andric if (S.getLangOpts().CUDA && VD->hasLocalStorage() && 45760fca6ea1SDimitry Andric S.CUDA().DiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared) 45770fca6ea1SDimitry Andric << llvm::to_underlying(S.CUDA().CurrentTarget())) 45780b57cec5SDimitry Andric return; 4579a7dea167SDimitry Andric D->addAttr(::new (S.Context) CUDASharedAttr(S.Context, AL)); 45800b57cec5SDimitry Andric } 45810b57cec5SDimitry Andric 45820b57cec5SDimitry Andric static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 45830b57cec5SDimitry Andric const auto *FD = cast<FunctionDecl>(D); 4584a7dea167SDimitry Andric if (!FD->getReturnType()->isVoidType() && 4585a7dea167SDimitry Andric !FD->getReturnType()->getAs<AutoType>() && 4586a7dea167SDimitry Andric !FD->getReturnType()->isInstantiationDependentType()) { 45870b57cec5SDimitry Andric SourceRange RTRange = FD->getReturnTypeSourceRange(); 45880b57cec5SDimitry Andric S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) 45890b57cec5SDimitry Andric << FD->getType() 45900b57cec5SDimitry Andric << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void") 45910b57cec5SDimitry Andric : FixItHint()); 45920b57cec5SDimitry Andric return; 45930b57cec5SDimitry Andric } 45940b57cec5SDimitry Andric if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) { 45950b57cec5SDimitry Andric if (Method->isInstance()) { 45960b57cec5SDimitry Andric S.Diag(Method->getBeginLoc(), diag::err_kern_is_nonstatic_method) 45970b57cec5SDimitry Andric << Method; 45980b57cec5SDimitry Andric return; 45990b57cec5SDimitry Andric } 46000b57cec5SDimitry Andric S.Diag(Method->getBeginLoc(), diag::warn_kern_is_method) << Method; 46010b57cec5SDimitry Andric } 46020b57cec5SDimitry Andric // Only warn for "inline" when compiling for host, to cut down on noise. 46030b57cec5SDimitry Andric if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice) 46040b57cec5SDimitry Andric S.Diag(FD->getBeginLoc(), diag::warn_kern_is_inline) << FD; 46050b57cec5SDimitry Andric 460606c3fb27SDimitry Andric if (AL.getKind() == ParsedAttr::AT_NVPTXKernel) 460706c3fb27SDimitry Andric D->addAttr(::new (S.Context) NVPTXKernelAttr(S.Context, AL)); 460806c3fb27SDimitry Andric else 4609a7dea167SDimitry Andric D->addAttr(::new (S.Context) CUDAGlobalAttr(S.Context, AL)); 46105ffd83dbSDimitry Andric // In host compilation the kernel is emitted as a stub function, which is 46115ffd83dbSDimitry Andric // a helper function for launching the kernel. The instructions in the helper 46125ffd83dbSDimitry Andric // function has nothing to do with the source code of the kernel. Do not emit 46135ffd83dbSDimitry Andric // debug info for the stub function to avoid confusing the debugger. 46145ffd83dbSDimitry Andric if (S.LangOpts.HIP && !S.LangOpts.CUDAIsDevice) 46155ffd83dbSDimitry Andric D->addAttr(NoDebugAttr::CreateImplicit(S.Context)); 46160b57cec5SDimitry Andric } 46170b57cec5SDimitry Andric 4618e8d8bef9SDimitry Andric static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4619e8d8bef9SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D)) { 4620e8d8bef9SDimitry Andric if (VD->hasLocalStorage()) { 4621e8d8bef9SDimitry Andric S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); 4622e8d8bef9SDimitry Andric return; 4623e8d8bef9SDimitry Andric } 4624e8d8bef9SDimitry Andric } 4625e8d8bef9SDimitry Andric 4626e8d8bef9SDimitry Andric if (auto *A = D->getAttr<CUDADeviceAttr>()) { 4627e8d8bef9SDimitry Andric if (!A->isImplicit()) 4628e8d8bef9SDimitry Andric return; 4629e8d8bef9SDimitry Andric D->dropAttr<CUDADeviceAttr>(); 4630e8d8bef9SDimitry Andric } 4631e8d8bef9SDimitry Andric D->addAttr(::new (S.Context) CUDADeviceAttr(S.Context, AL)); 4632e8d8bef9SDimitry Andric } 4633e8d8bef9SDimitry Andric 4634e8d8bef9SDimitry Andric static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4635e8d8bef9SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D)) { 4636e8d8bef9SDimitry Andric if (VD->hasLocalStorage()) { 4637e8d8bef9SDimitry Andric S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); 4638e8d8bef9SDimitry Andric return; 4639e8d8bef9SDimitry Andric } 4640e8d8bef9SDimitry Andric } 4641e8d8bef9SDimitry Andric if (!D->hasAttr<HIPManagedAttr>()) 4642e8d8bef9SDimitry Andric D->addAttr(::new (S.Context) HIPManagedAttr(S.Context, AL)); 4643e8d8bef9SDimitry Andric if (!D->hasAttr<CUDADeviceAttr>()) 4644e8d8bef9SDimitry Andric D->addAttr(CUDADeviceAttr::CreateImplicit(S.Context)); 4645e8d8bef9SDimitry Andric } 4646e8d8bef9SDimitry Andric 46470b57cec5SDimitry Andric static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 46480b57cec5SDimitry Andric const auto *Fn = cast<FunctionDecl>(D); 46490b57cec5SDimitry Andric if (!Fn->isInlineSpecified()) { 46500b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); 46510b57cec5SDimitry Andric return; 46520b57cec5SDimitry Andric } 46530b57cec5SDimitry Andric 4654a7dea167SDimitry Andric if (S.LangOpts.CPlusPlus && Fn->getStorageClass() != SC_Extern) 4655a7dea167SDimitry Andric S.Diag(AL.getLoc(), diag::warn_gnu_inline_cplusplus_without_extern); 4656a7dea167SDimitry Andric 4657a7dea167SDimitry Andric D->addAttr(::new (S.Context) GNUInlineAttr(S.Context, AL)); 46580b57cec5SDimitry Andric } 46590b57cec5SDimitry Andric 46600b57cec5SDimitry Andric static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 46610b57cec5SDimitry Andric if (hasDeclarator(D)) return; 46620b57cec5SDimitry Andric 46630b57cec5SDimitry Andric // Diagnostic is emitted elsewhere: here we store the (valid) AL 46640b57cec5SDimitry Andric // in the Decl node for syntactic reasoning, e.g., pretty-printing. 46650b57cec5SDimitry Andric CallingConv CC; 46660fca6ea1SDimitry Andric if (S.CheckCallingConvAttr( 46670fca6ea1SDimitry Andric AL, CC, /*FD*/ nullptr, 46680fca6ea1SDimitry Andric S.CUDA().IdentifyTarget(dyn_cast<FunctionDecl>(D)))) 46690b57cec5SDimitry Andric return; 46700b57cec5SDimitry Andric 46710b57cec5SDimitry Andric if (!isa<ObjCMethodDecl>(D)) { 46720b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 467306c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() << ExpectedFunctionOrMethod; 46740b57cec5SDimitry Andric return; 46750b57cec5SDimitry Andric } 46760b57cec5SDimitry Andric 46770b57cec5SDimitry Andric switch (AL.getKind()) { 46780b57cec5SDimitry Andric case ParsedAttr::AT_FastCall: 4679a7dea167SDimitry Andric D->addAttr(::new (S.Context) FastCallAttr(S.Context, AL)); 46800b57cec5SDimitry Andric return; 46810b57cec5SDimitry Andric case ParsedAttr::AT_StdCall: 4682a7dea167SDimitry Andric D->addAttr(::new (S.Context) StdCallAttr(S.Context, AL)); 46830b57cec5SDimitry Andric return; 46840b57cec5SDimitry Andric case ParsedAttr::AT_ThisCall: 4685a7dea167SDimitry Andric D->addAttr(::new (S.Context) ThisCallAttr(S.Context, AL)); 46860b57cec5SDimitry Andric return; 46870b57cec5SDimitry Andric case ParsedAttr::AT_CDecl: 4688a7dea167SDimitry Andric D->addAttr(::new (S.Context) CDeclAttr(S.Context, AL)); 46890b57cec5SDimitry Andric return; 46900b57cec5SDimitry Andric case ParsedAttr::AT_Pascal: 4691a7dea167SDimitry Andric D->addAttr(::new (S.Context) PascalAttr(S.Context, AL)); 46920b57cec5SDimitry Andric return; 46930b57cec5SDimitry Andric case ParsedAttr::AT_SwiftCall: 4694a7dea167SDimitry Andric D->addAttr(::new (S.Context) SwiftCallAttr(S.Context, AL)); 46950b57cec5SDimitry Andric return; 4696fe6060f1SDimitry Andric case ParsedAttr::AT_SwiftAsyncCall: 4697fe6060f1SDimitry Andric D->addAttr(::new (S.Context) SwiftAsyncCallAttr(S.Context, AL)); 4698fe6060f1SDimitry Andric return; 46990b57cec5SDimitry Andric case ParsedAttr::AT_VectorCall: 4700a7dea167SDimitry Andric D->addAttr(::new (S.Context) VectorCallAttr(S.Context, AL)); 47010b57cec5SDimitry Andric return; 47020b57cec5SDimitry Andric case ParsedAttr::AT_MSABI: 4703a7dea167SDimitry Andric D->addAttr(::new (S.Context) MSABIAttr(S.Context, AL)); 47040b57cec5SDimitry Andric return; 47050b57cec5SDimitry Andric case ParsedAttr::AT_SysVABI: 4706a7dea167SDimitry Andric D->addAttr(::new (S.Context) SysVABIAttr(S.Context, AL)); 47070b57cec5SDimitry Andric return; 47080b57cec5SDimitry Andric case ParsedAttr::AT_RegCall: 4709a7dea167SDimitry Andric D->addAttr(::new (S.Context) RegCallAttr(S.Context, AL)); 47100b57cec5SDimitry Andric return; 47110b57cec5SDimitry Andric case ParsedAttr::AT_Pcs: { 47120b57cec5SDimitry Andric PcsAttr::PCSType PCS; 47130b57cec5SDimitry Andric switch (CC) { 47140b57cec5SDimitry Andric case CC_AAPCS: 47150b57cec5SDimitry Andric PCS = PcsAttr::AAPCS; 47160b57cec5SDimitry Andric break; 47170b57cec5SDimitry Andric case CC_AAPCS_VFP: 47180b57cec5SDimitry Andric PCS = PcsAttr::AAPCS_VFP; 47190b57cec5SDimitry Andric break; 47200b57cec5SDimitry Andric default: 47210b57cec5SDimitry Andric llvm_unreachable("unexpected calling convention in pcs attribute"); 47220b57cec5SDimitry Andric } 47230b57cec5SDimitry Andric 4724a7dea167SDimitry Andric D->addAttr(::new (S.Context) PcsAttr(S.Context, AL, PCS)); 47250b57cec5SDimitry Andric return; 47260b57cec5SDimitry Andric } 47270b57cec5SDimitry Andric case ParsedAttr::AT_AArch64VectorPcs: 4728a7dea167SDimitry Andric D->addAttr(::new (S.Context) AArch64VectorPcsAttr(S.Context, AL)); 47290b57cec5SDimitry Andric return; 473081ad6265SDimitry Andric case ParsedAttr::AT_AArch64SVEPcs: 473181ad6265SDimitry Andric D->addAttr(::new (S.Context) AArch64SVEPcsAttr(S.Context, AL)); 473281ad6265SDimitry Andric return; 473381ad6265SDimitry Andric case ParsedAttr::AT_AMDGPUKernelCall: 473481ad6265SDimitry Andric D->addAttr(::new (S.Context) AMDGPUKernelCallAttr(S.Context, AL)); 473581ad6265SDimitry Andric return; 47360b57cec5SDimitry Andric case ParsedAttr::AT_IntelOclBicc: 4737a7dea167SDimitry Andric D->addAttr(::new (S.Context) IntelOclBiccAttr(S.Context, AL)); 47380b57cec5SDimitry Andric return; 47390b57cec5SDimitry Andric case ParsedAttr::AT_PreserveMost: 4740a7dea167SDimitry Andric D->addAttr(::new (S.Context) PreserveMostAttr(S.Context, AL)); 47410b57cec5SDimitry Andric return; 47420b57cec5SDimitry Andric case ParsedAttr::AT_PreserveAll: 4743a7dea167SDimitry Andric D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL)); 47440b57cec5SDimitry Andric return; 47455f757f3fSDimitry Andric case ParsedAttr::AT_M68kRTD: 47465f757f3fSDimitry Andric D->addAttr(::new (S.Context) M68kRTDAttr(S.Context, AL)); 47475f757f3fSDimitry Andric return; 47480fca6ea1SDimitry Andric case ParsedAttr::AT_PreserveNone: 47490fca6ea1SDimitry Andric D->addAttr(::new (S.Context) PreserveNoneAttr(S.Context, AL)); 47500fca6ea1SDimitry Andric return; 47510fca6ea1SDimitry Andric case ParsedAttr::AT_RISCVVectorCC: 47520fca6ea1SDimitry Andric D->addAttr(::new (S.Context) RISCVVectorCCAttr(S.Context, AL)); 47530fca6ea1SDimitry Andric return; 47540b57cec5SDimitry Andric default: 47550b57cec5SDimitry Andric llvm_unreachable("unexpected attribute kind"); 47560b57cec5SDimitry Andric } 47570b57cec5SDimitry Andric } 47580b57cec5SDimitry Andric 47590b57cec5SDimitry Andric static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 47605f757f3fSDimitry Andric if (AL.getAttributeSpellingListIndex() == SuppressAttr::CXX11_gsl_suppress) { 47615f757f3fSDimitry Andric // Suppression attribute with GSL spelling requires at least 1 argument. 4762fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1)) 47630b57cec5SDimitry Andric return; 47645f757f3fSDimitry Andric } 47650b57cec5SDimitry Andric 47660b57cec5SDimitry Andric std::vector<StringRef> DiagnosticIdentifiers; 47670b57cec5SDimitry Andric for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { 47680b57cec5SDimitry Andric StringRef RuleName; 47690b57cec5SDimitry Andric 47700b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, I, RuleName, nullptr)) 47710b57cec5SDimitry Andric return; 47720b57cec5SDimitry Andric 47730b57cec5SDimitry Andric DiagnosticIdentifiers.push_back(RuleName); 47740b57cec5SDimitry Andric } 4775a7dea167SDimitry Andric D->addAttr(::new (S.Context) 4776a7dea167SDimitry Andric SuppressAttr(S.Context, AL, DiagnosticIdentifiers.data(), 4777a7dea167SDimitry Andric DiagnosticIdentifiers.size())); 4778a7dea167SDimitry Andric } 4779a7dea167SDimitry Andric 4780a7dea167SDimitry Andric static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 4781a7dea167SDimitry Andric TypeSourceInfo *DerefTypeLoc = nullptr; 4782a7dea167SDimitry Andric QualType ParmType; 4783a7dea167SDimitry Andric if (AL.hasParsedType()) { 4784a7dea167SDimitry Andric ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc); 4785a7dea167SDimitry Andric 4786a7dea167SDimitry Andric unsigned SelectIdx = ~0U; 4787480093f4SDimitry Andric if (ParmType->isReferenceType()) 4788a7dea167SDimitry Andric SelectIdx = 0; 4789a7dea167SDimitry Andric else if (ParmType->isArrayType()) 4790480093f4SDimitry Andric SelectIdx = 1; 4791a7dea167SDimitry Andric 4792a7dea167SDimitry Andric if (SelectIdx != ~0U) { 4793a7dea167SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) 4794a7dea167SDimitry Andric << SelectIdx << AL; 4795a7dea167SDimitry Andric return; 4796a7dea167SDimitry Andric } 4797a7dea167SDimitry Andric } 4798a7dea167SDimitry Andric 4799a7dea167SDimitry Andric // To check if earlier decl attributes do not conflict the newly parsed ones 4800349cc55cSDimitry Andric // we always add (and check) the attribute to the canonical decl. We need 4801fe6060f1SDimitry Andric // to repeat the check for attribute mutual exclusion because we're attaching 4802fe6060f1SDimitry Andric // all of the attributes to the canonical declaration rather than the current 4803fe6060f1SDimitry Andric // declaration. 4804a7dea167SDimitry Andric D = D->getCanonicalDecl(); 4805a7dea167SDimitry Andric if (AL.getKind() == ParsedAttr::AT_Owner) { 4806a7dea167SDimitry Andric if (checkAttrMutualExclusion<PointerAttr>(S, D, AL)) 4807a7dea167SDimitry Andric return; 4808a7dea167SDimitry Andric if (const auto *OAttr = D->getAttr<OwnerAttr>()) { 4809a7dea167SDimitry Andric const Type *ExistingDerefType = OAttr->getDerefTypeLoc() 4810a7dea167SDimitry Andric ? OAttr->getDerefType().getTypePtr() 4811a7dea167SDimitry Andric : nullptr; 4812a7dea167SDimitry Andric if (ExistingDerefType != ParmType.getTypePtrOrNull()) { 4813a7dea167SDimitry Andric S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) 481406c3fb27SDimitry Andric << AL << OAttr 481506c3fb27SDimitry Andric << (AL.isRegularKeywordAttribute() || 481606c3fb27SDimitry Andric OAttr->isRegularKeywordAttribute()); 4817a7dea167SDimitry Andric S.Diag(OAttr->getLocation(), diag::note_conflicting_attribute); 4818a7dea167SDimitry Andric } 4819a7dea167SDimitry Andric return; 4820a7dea167SDimitry Andric } 4821a7dea167SDimitry Andric for (Decl *Redecl : D->redecls()) { 4822a7dea167SDimitry Andric Redecl->addAttr(::new (S.Context) OwnerAttr(S.Context, AL, DerefTypeLoc)); 4823a7dea167SDimitry Andric } 4824a7dea167SDimitry Andric } else { 4825a7dea167SDimitry Andric if (checkAttrMutualExclusion<OwnerAttr>(S, D, AL)) 4826a7dea167SDimitry Andric return; 4827a7dea167SDimitry Andric if (const auto *PAttr = D->getAttr<PointerAttr>()) { 4828a7dea167SDimitry Andric const Type *ExistingDerefType = PAttr->getDerefTypeLoc() 4829a7dea167SDimitry Andric ? PAttr->getDerefType().getTypePtr() 4830a7dea167SDimitry Andric : nullptr; 4831a7dea167SDimitry Andric if (ExistingDerefType != ParmType.getTypePtrOrNull()) { 4832a7dea167SDimitry Andric S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) 483306c3fb27SDimitry Andric << AL << PAttr 483406c3fb27SDimitry Andric << (AL.isRegularKeywordAttribute() || 483506c3fb27SDimitry Andric PAttr->isRegularKeywordAttribute()); 4836a7dea167SDimitry Andric S.Diag(PAttr->getLocation(), diag::note_conflicting_attribute); 4837a7dea167SDimitry Andric } 4838a7dea167SDimitry Andric return; 4839a7dea167SDimitry Andric } 4840a7dea167SDimitry Andric for (Decl *Redecl : D->redecls()) { 4841a7dea167SDimitry Andric Redecl->addAttr(::new (S.Context) 4842a7dea167SDimitry Andric PointerAttr(S.Context, AL, DerefTypeLoc)); 4843a7dea167SDimitry Andric } 4844a7dea167SDimitry Andric } 48450b57cec5SDimitry Andric } 48460b57cec5SDimitry Andric 484781ad6265SDimitry Andric static void handleRandomizeLayoutAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 484881ad6265SDimitry Andric if (checkAttrMutualExclusion<NoRandomizeLayoutAttr>(S, D, AL)) 484981ad6265SDimitry Andric return; 485081ad6265SDimitry Andric if (!D->hasAttr<RandomizeLayoutAttr>()) 485181ad6265SDimitry Andric D->addAttr(::new (S.Context) RandomizeLayoutAttr(S.Context, AL)); 485281ad6265SDimitry Andric } 485381ad6265SDimitry Andric 485481ad6265SDimitry Andric static void handleNoRandomizeLayoutAttr(Sema &S, Decl *D, 485581ad6265SDimitry Andric const ParsedAttr &AL) { 485681ad6265SDimitry Andric if (checkAttrMutualExclusion<RandomizeLayoutAttr>(S, D, AL)) 485781ad6265SDimitry Andric return; 485881ad6265SDimitry Andric if (!D->hasAttr<NoRandomizeLayoutAttr>()) 485981ad6265SDimitry Andric D->addAttr(::new (S.Context) NoRandomizeLayoutAttr(S.Context, AL)); 486081ad6265SDimitry Andric } 486181ad6265SDimitry Andric 48620b57cec5SDimitry Andric bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, 48635f757f3fSDimitry Andric const FunctionDecl *FD, 48645f757f3fSDimitry Andric CUDAFunctionTarget CFT) { 48650b57cec5SDimitry Andric if (Attrs.isInvalid()) 48660b57cec5SDimitry Andric return true; 48670b57cec5SDimitry Andric 48680b57cec5SDimitry Andric if (Attrs.hasProcessingCache()) { 48690b57cec5SDimitry Andric CC = (CallingConv) Attrs.getProcessingCache(); 48700b57cec5SDimitry Andric return false; 48710b57cec5SDimitry Andric } 48720b57cec5SDimitry Andric 48730b57cec5SDimitry Andric unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0; 4874fe6060f1SDimitry Andric if (!Attrs.checkExactlyNumArgs(*this, ReqArgs)) { 48750b57cec5SDimitry Andric Attrs.setInvalid(); 48760b57cec5SDimitry Andric return true; 48770b57cec5SDimitry Andric } 48780b57cec5SDimitry Andric 48790b57cec5SDimitry Andric // TODO: diagnose uses of these conventions on the wrong target. 48800b57cec5SDimitry Andric switch (Attrs.getKind()) { 48810b57cec5SDimitry Andric case ParsedAttr::AT_CDecl: 48820b57cec5SDimitry Andric CC = CC_C; 48830b57cec5SDimitry Andric break; 48840b57cec5SDimitry Andric case ParsedAttr::AT_FastCall: 48850b57cec5SDimitry Andric CC = CC_X86FastCall; 48860b57cec5SDimitry Andric break; 48870b57cec5SDimitry Andric case ParsedAttr::AT_StdCall: 48880b57cec5SDimitry Andric CC = CC_X86StdCall; 48890b57cec5SDimitry Andric break; 48900b57cec5SDimitry Andric case ParsedAttr::AT_ThisCall: 48910b57cec5SDimitry Andric CC = CC_X86ThisCall; 48920b57cec5SDimitry Andric break; 48930b57cec5SDimitry Andric case ParsedAttr::AT_Pascal: 48940b57cec5SDimitry Andric CC = CC_X86Pascal; 48950b57cec5SDimitry Andric break; 48960b57cec5SDimitry Andric case ParsedAttr::AT_SwiftCall: 48970b57cec5SDimitry Andric CC = CC_Swift; 48980b57cec5SDimitry Andric break; 4899fe6060f1SDimitry Andric case ParsedAttr::AT_SwiftAsyncCall: 4900fe6060f1SDimitry Andric CC = CC_SwiftAsync; 4901fe6060f1SDimitry Andric break; 49020b57cec5SDimitry Andric case ParsedAttr::AT_VectorCall: 49030b57cec5SDimitry Andric CC = CC_X86VectorCall; 49040b57cec5SDimitry Andric break; 49050b57cec5SDimitry Andric case ParsedAttr::AT_AArch64VectorPcs: 49060b57cec5SDimitry Andric CC = CC_AArch64VectorCall; 49070b57cec5SDimitry Andric break; 490881ad6265SDimitry Andric case ParsedAttr::AT_AArch64SVEPcs: 490981ad6265SDimitry Andric CC = CC_AArch64SVEPCS; 491081ad6265SDimitry Andric break; 491181ad6265SDimitry Andric case ParsedAttr::AT_AMDGPUKernelCall: 491281ad6265SDimitry Andric CC = CC_AMDGPUKernelCall; 491381ad6265SDimitry Andric break; 49140b57cec5SDimitry Andric case ParsedAttr::AT_RegCall: 49150b57cec5SDimitry Andric CC = CC_X86RegCall; 49160b57cec5SDimitry Andric break; 49170b57cec5SDimitry Andric case ParsedAttr::AT_MSABI: 49180b57cec5SDimitry Andric CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : 49190b57cec5SDimitry Andric CC_Win64; 49200b57cec5SDimitry Andric break; 49210b57cec5SDimitry Andric case ParsedAttr::AT_SysVABI: 49220b57cec5SDimitry Andric CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : 49230b57cec5SDimitry Andric CC_C; 49240b57cec5SDimitry Andric break; 49250b57cec5SDimitry Andric case ParsedAttr::AT_Pcs: { 49260b57cec5SDimitry Andric StringRef StrRef; 49270b57cec5SDimitry Andric if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) { 49280b57cec5SDimitry Andric Attrs.setInvalid(); 49290b57cec5SDimitry Andric return true; 49300b57cec5SDimitry Andric } 49310b57cec5SDimitry Andric if (StrRef == "aapcs") { 49320b57cec5SDimitry Andric CC = CC_AAPCS; 49330b57cec5SDimitry Andric break; 49340b57cec5SDimitry Andric } else if (StrRef == "aapcs-vfp") { 49350b57cec5SDimitry Andric CC = CC_AAPCS_VFP; 49360b57cec5SDimitry Andric break; 49370b57cec5SDimitry Andric } 49380b57cec5SDimitry Andric 49390b57cec5SDimitry Andric Attrs.setInvalid(); 49400b57cec5SDimitry Andric Diag(Attrs.getLoc(), diag::err_invalid_pcs); 49410b57cec5SDimitry Andric return true; 49420b57cec5SDimitry Andric } 49430b57cec5SDimitry Andric case ParsedAttr::AT_IntelOclBicc: 49440b57cec5SDimitry Andric CC = CC_IntelOclBicc; 49450b57cec5SDimitry Andric break; 49460b57cec5SDimitry Andric case ParsedAttr::AT_PreserveMost: 49470b57cec5SDimitry Andric CC = CC_PreserveMost; 49480b57cec5SDimitry Andric break; 49490b57cec5SDimitry Andric case ParsedAttr::AT_PreserveAll: 49500b57cec5SDimitry Andric CC = CC_PreserveAll; 49510b57cec5SDimitry Andric break; 49525f757f3fSDimitry Andric case ParsedAttr::AT_M68kRTD: 49535f757f3fSDimitry Andric CC = CC_M68kRTD; 49545f757f3fSDimitry Andric break; 49550fca6ea1SDimitry Andric case ParsedAttr::AT_PreserveNone: 49560fca6ea1SDimitry Andric CC = CC_PreserveNone; 49570fca6ea1SDimitry Andric break; 49580fca6ea1SDimitry Andric case ParsedAttr::AT_RISCVVectorCC: 49590fca6ea1SDimitry Andric CC = CC_RISCVVectorCall; 49600fca6ea1SDimitry Andric break; 49610b57cec5SDimitry Andric default: llvm_unreachable("unexpected attribute kind"); 49620b57cec5SDimitry Andric } 49630b57cec5SDimitry Andric 49640b57cec5SDimitry Andric TargetInfo::CallingConvCheckResult A = TargetInfo::CCCR_OK; 49650b57cec5SDimitry Andric const TargetInfo &TI = Context.getTargetInfo(); 49660b57cec5SDimitry Andric // CUDA functions may have host and/or device attributes which indicate 49670b57cec5SDimitry Andric // their targeted execution environment, therefore the calling convention 49680b57cec5SDimitry Andric // of functions in CUDA should be checked against the target deduced based 49690b57cec5SDimitry Andric // on their host/device attributes. 49700b57cec5SDimitry Andric if (LangOpts.CUDA) { 49710b57cec5SDimitry Andric auto *Aux = Context.getAuxTargetInfo(); 49720fca6ea1SDimitry Andric assert(FD || CFT != CUDAFunctionTarget::InvalidTarget); 49730fca6ea1SDimitry Andric auto CudaTarget = FD ? CUDA().IdentifyTarget(FD) : CFT; 49740b57cec5SDimitry Andric bool CheckHost = false, CheckDevice = false; 49750b57cec5SDimitry Andric switch (CudaTarget) { 49760fca6ea1SDimitry Andric case CUDAFunctionTarget::HostDevice: 49770b57cec5SDimitry Andric CheckHost = true; 49780b57cec5SDimitry Andric CheckDevice = true; 49790b57cec5SDimitry Andric break; 49800fca6ea1SDimitry Andric case CUDAFunctionTarget::Host: 49810b57cec5SDimitry Andric CheckHost = true; 49820b57cec5SDimitry Andric break; 49830fca6ea1SDimitry Andric case CUDAFunctionTarget::Device: 49840fca6ea1SDimitry Andric case CUDAFunctionTarget::Global: 49850b57cec5SDimitry Andric CheckDevice = true; 49860b57cec5SDimitry Andric break; 49870fca6ea1SDimitry Andric case CUDAFunctionTarget::InvalidTarget: 49880b57cec5SDimitry Andric llvm_unreachable("unexpected cuda target"); 49890b57cec5SDimitry Andric } 49900b57cec5SDimitry Andric auto *HostTI = LangOpts.CUDAIsDevice ? Aux : &TI; 49910b57cec5SDimitry Andric auto *DeviceTI = LangOpts.CUDAIsDevice ? &TI : Aux; 49920b57cec5SDimitry Andric if (CheckHost && HostTI) 49930b57cec5SDimitry Andric A = HostTI->checkCallingConvention(CC); 49940b57cec5SDimitry Andric if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI) 49950b57cec5SDimitry Andric A = DeviceTI->checkCallingConvention(CC); 49960b57cec5SDimitry Andric } else { 49970b57cec5SDimitry Andric A = TI.checkCallingConvention(CC); 49980b57cec5SDimitry Andric } 49990b57cec5SDimitry Andric 50000b57cec5SDimitry Andric switch (A) { 50010b57cec5SDimitry Andric case TargetInfo::CCCR_OK: 50020b57cec5SDimitry Andric break; 50030b57cec5SDimitry Andric 50040b57cec5SDimitry Andric case TargetInfo::CCCR_Ignore: 50050b57cec5SDimitry Andric // Treat an ignored convention as if it was an explicit C calling convention 50060b57cec5SDimitry Andric // attribute. For example, __stdcall on Win x64 functions as __cdecl, so 50070b57cec5SDimitry Andric // that command line flags that change the default convention to 50080b57cec5SDimitry Andric // __vectorcall don't affect declarations marked __stdcall. 50090b57cec5SDimitry Andric CC = CC_C; 50100b57cec5SDimitry Andric break; 50110b57cec5SDimitry Andric 5012a7dea167SDimitry Andric case TargetInfo::CCCR_Error: 5013a7dea167SDimitry Andric Diag(Attrs.getLoc(), diag::error_cconv_unsupported) 5014a7dea167SDimitry Andric << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget; 5015a7dea167SDimitry Andric break; 5016a7dea167SDimitry Andric 50170b57cec5SDimitry Andric case TargetInfo::CCCR_Warning: { 50180b57cec5SDimitry Andric Diag(Attrs.getLoc(), diag::warn_cconv_unsupported) 50190b57cec5SDimitry Andric << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget; 50200b57cec5SDimitry Andric 50210b57cec5SDimitry Andric // This convention is not valid for the target. Use the default function or 50220b57cec5SDimitry Andric // method calling convention. 50230b57cec5SDimitry Andric bool IsCXXMethod = false, IsVariadic = false; 50240b57cec5SDimitry Andric if (FD) { 50250b57cec5SDimitry Andric IsCXXMethod = FD->isCXXInstanceMember(); 50260b57cec5SDimitry Andric IsVariadic = FD->isVariadic(); 50270b57cec5SDimitry Andric } 50280b57cec5SDimitry Andric CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod); 50290b57cec5SDimitry Andric break; 50300b57cec5SDimitry Andric } 50310b57cec5SDimitry Andric } 50320b57cec5SDimitry Andric 50330b57cec5SDimitry Andric Attrs.setProcessingCache((unsigned) CC); 50340b57cec5SDimitry Andric return false; 50350b57cec5SDimitry Andric } 50360b57cec5SDimitry Andric 50370b57cec5SDimitry Andric bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) { 50380b57cec5SDimitry Andric if (AL.isInvalid()) 50390b57cec5SDimitry Andric return true; 50400b57cec5SDimitry Andric 5041fe6060f1SDimitry Andric if (!AL.checkExactlyNumArgs(*this, 1)) { 50420b57cec5SDimitry Andric AL.setInvalid(); 50430b57cec5SDimitry Andric return true; 50440b57cec5SDimitry Andric } 50450b57cec5SDimitry Andric 50460b57cec5SDimitry Andric uint32_t NP; 50470b57cec5SDimitry Andric Expr *NumParamsExpr = AL.getArgAsExpr(0); 50480fca6ea1SDimitry Andric if (!checkUInt32Argument(AL, NumParamsExpr, NP)) { 50490b57cec5SDimitry Andric AL.setInvalid(); 50500b57cec5SDimitry Andric return true; 50510b57cec5SDimitry Andric } 50520b57cec5SDimitry Andric 50530b57cec5SDimitry Andric if (Context.getTargetInfo().getRegParmMax() == 0) { 50540b57cec5SDimitry Andric Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform) 50550b57cec5SDimitry Andric << NumParamsExpr->getSourceRange(); 50560b57cec5SDimitry Andric AL.setInvalid(); 50570b57cec5SDimitry Andric return true; 50580b57cec5SDimitry Andric } 50590b57cec5SDimitry Andric 50600b57cec5SDimitry Andric numParams = NP; 50610b57cec5SDimitry Andric if (numParams > Context.getTargetInfo().getRegParmMax()) { 50620b57cec5SDimitry Andric Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number) 50630b57cec5SDimitry Andric << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange(); 50640b57cec5SDimitry Andric AL.setInvalid(); 50650b57cec5SDimitry Andric return true; 50660b57cec5SDimitry Andric } 50670b57cec5SDimitry Andric 50680b57cec5SDimitry Andric return false; 50690b57cec5SDimitry Andric } 50700b57cec5SDimitry Andric 50710fca6ea1SDimitry Andric // Helper to get OffloadArch. 50720fca6ea1SDimitry Andric static OffloadArch getOffloadArch(const TargetInfo &TI) { 50735f757f3fSDimitry Andric if (!TI.getTriple().isNVPTX()) 50740fca6ea1SDimitry Andric llvm_unreachable("getOffloadArch is only valid for NVPTX triple"); 50755f757f3fSDimitry Andric auto &TO = TI.getTargetOpts(); 50760fca6ea1SDimitry Andric return StringToOffloadArch(TO.CPU); 50775f757f3fSDimitry Andric } 50785f757f3fSDimitry Andric 50790b57cec5SDimitry Andric // Checks whether an argument of launch_bounds attribute is 50800b57cec5SDimitry Andric // acceptable, performs implicit conversion to Rvalue, and returns 50810b57cec5SDimitry Andric // non-nullptr Expr result on success. Otherwise, it returns nullptr 50820b57cec5SDimitry Andric // and may output an error. 50830b57cec5SDimitry Andric static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E, 50840b57cec5SDimitry Andric const CUDALaunchBoundsAttr &AL, 50850b57cec5SDimitry Andric const unsigned Idx) { 50860b57cec5SDimitry Andric if (S.DiagnoseUnexpandedParameterPack(E)) 50870b57cec5SDimitry Andric return nullptr; 50880b57cec5SDimitry Andric 50890b57cec5SDimitry Andric // Accept template arguments for now as they depend on something else. 50900b57cec5SDimitry Andric // We'll get to check them when they eventually get instantiated. 50910b57cec5SDimitry Andric if (E->isValueDependent()) 50920b57cec5SDimitry Andric return E; 50930b57cec5SDimitry Andric 5094bdd1243dSDimitry Andric std::optional<llvm::APSInt> I = llvm::APSInt(64); 5095e8d8bef9SDimitry Andric if (!(I = E->getIntegerConstantExpr(S.Context))) { 50960b57cec5SDimitry Andric S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) 50970b57cec5SDimitry Andric << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); 50980b57cec5SDimitry Andric return nullptr; 50990b57cec5SDimitry Andric } 51000b57cec5SDimitry Andric // Make sure we can fit it in 32 bits. 5101e8d8bef9SDimitry Andric if (!I->isIntN(32)) { 5102e8d8bef9SDimitry Andric S.Diag(E->getExprLoc(), diag::err_ice_too_large) 5103fe6060f1SDimitry Andric << toString(*I, 10, false) << 32 << /* Unsigned */ 1; 51040b57cec5SDimitry Andric return nullptr; 51050b57cec5SDimitry Andric } 5106e8d8bef9SDimitry Andric if (*I < 0) 51070b57cec5SDimitry Andric S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) 51080b57cec5SDimitry Andric << &AL << Idx << E->getSourceRange(); 51090b57cec5SDimitry Andric 51100b57cec5SDimitry Andric // We may need to perform implicit conversion of the argument. 51110b57cec5SDimitry Andric InitializedEntity Entity = InitializedEntity::InitializeParameter( 51120b57cec5SDimitry Andric S.Context, S.Context.getConstType(S.Context.IntTy), /*consume*/ false); 51130b57cec5SDimitry Andric ExprResult ValArg = S.PerformCopyInitialization(Entity, SourceLocation(), E); 51140b57cec5SDimitry Andric assert(!ValArg.isInvalid() && 51150b57cec5SDimitry Andric "Unexpected PerformCopyInitialization() failure."); 51160b57cec5SDimitry Andric 51170b57cec5SDimitry Andric return ValArg.getAs<Expr>(); 51180b57cec5SDimitry Andric } 51190b57cec5SDimitry Andric 51205f757f3fSDimitry Andric CUDALaunchBoundsAttr * 51215f757f3fSDimitry Andric Sema::CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, Expr *MaxThreads, 51225f757f3fSDimitry Andric Expr *MinBlocks, Expr *MaxBlocks) { 51235f757f3fSDimitry Andric CUDALaunchBoundsAttr TmpAttr(Context, CI, MaxThreads, MinBlocks, MaxBlocks); 51240b57cec5SDimitry Andric MaxThreads = makeLaunchBoundsArgExpr(*this, MaxThreads, TmpAttr, 0); 51255f757f3fSDimitry Andric if (!MaxThreads) 51265f757f3fSDimitry Andric return nullptr; 51270b57cec5SDimitry Andric 51280b57cec5SDimitry Andric if (MinBlocks) { 51290b57cec5SDimitry Andric MinBlocks = makeLaunchBoundsArgExpr(*this, MinBlocks, TmpAttr, 1); 51305f757f3fSDimitry Andric if (!MinBlocks) 51315f757f3fSDimitry Andric return nullptr; 51320b57cec5SDimitry Andric } 51330b57cec5SDimitry Andric 51345f757f3fSDimitry Andric if (MaxBlocks) { 51355f757f3fSDimitry Andric // '.maxclusterrank' ptx directive requires .target sm_90 or higher. 51360fca6ea1SDimitry Andric auto SM = getOffloadArch(Context.getTargetInfo()); 51370fca6ea1SDimitry Andric if (SM == OffloadArch::UNKNOWN || SM < OffloadArch::SM_90) { 51385f757f3fSDimitry Andric Diag(MaxBlocks->getBeginLoc(), diag::warn_cuda_maxclusterrank_sm_90) 51390fca6ea1SDimitry Andric << OffloadArchToString(SM) << CI << MaxBlocks->getSourceRange(); 51405f757f3fSDimitry Andric // Ignore it by setting MaxBlocks to null; 51415f757f3fSDimitry Andric MaxBlocks = nullptr; 51425f757f3fSDimitry Andric } else { 51435f757f3fSDimitry Andric MaxBlocks = makeLaunchBoundsArgExpr(*this, MaxBlocks, TmpAttr, 2); 51445f757f3fSDimitry Andric if (!MaxBlocks) 51455f757f3fSDimitry Andric return nullptr; 51465f757f3fSDimitry Andric } 51475f757f3fSDimitry Andric } 51485f757f3fSDimitry Andric 51495f757f3fSDimitry Andric return ::new (Context) 51505f757f3fSDimitry Andric CUDALaunchBoundsAttr(Context, CI, MaxThreads, MinBlocks, MaxBlocks); 51515f757f3fSDimitry Andric } 51525f757f3fSDimitry Andric 51535f757f3fSDimitry Andric void Sema::AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI, 51545f757f3fSDimitry Andric Expr *MaxThreads, Expr *MinBlocks, 51555f757f3fSDimitry Andric Expr *MaxBlocks) { 51565f757f3fSDimitry Andric if (auto *Attr = CreateLaunchBoundsAttr(CI, MaxThreads, MinBlocks, MaxBlocks)) 51575f757f3fSDimitry Andric D->addAttr(Attr); 51580b57cec5SDimitry Andric } 51590b57cec5SDimitry Andric 51600b57cec5SDimitry Andric static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 51615f757f3fSDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3)) 51620b57cec5SDimitry Andric return; 51630b57cec5SDimitry Andric 5164a7dea167SDimitry Andric S.AddLaunchBoundsAttr(D, AL, AL.getArgAsExpr(0), 51655f757f3fSDimitry Andric AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr, 51665f757f3fSDimitry Andric AL.getNumArgs() > 2 ? AL.getArgAsExpr(2) : nullptr); 51670b57cec5SDimitry Andric } 51680b57cec5SDimitry Andric 51690b57cec5SDimitry Andric static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, 51700b57cec5SDimitry Andric const ParsedAttr &AL) { 51710b57cec5SDimitry Andric if (!AL.isArgIdent(0)) { 51720b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 51730b57cec5SDimitry Andric << AL << /* arg num = */ 1 << AANT_ArgumentIdentifier; 51740b57cec5SDimitry Andric return; 51750b57cec5SDimitry Andric } 51760b57cec5SDimitry Andric 51770b57cec5SDimitry Andric ParamIdx ArgumentIdx; 51780fca6ea1SDimitry Andric if (!S.checkFunctionOrMethodParameterIndex(D, AL, 2, AL.getArgAsExpr(1), 51790b57cec5SDimitry Andric ArgumentIdx)) 51800b57cec5SDimitry Andric return; 51810b57cec5SDimitry Andric 51820b57cec5SDimitry Andric ParamIdx TypeTagIdx; 51830fca6ea1SDimitry Andric if (!S.checkFunctionOrMethodParameterIndex(D, AL, 3, AL.getArgAsExpr(2), 51840b57cec5SDimitry Andric TypeTagIdx)) 51850b57cec5SDimitry Andric return; 51860b57cec5SDimitry Andric 5187a7dea167SDimitry Andric bool IsPointer = AL.getAttrName()->getName() == "pointer_with_type_tag"; 51880b57cec5SDimitry Andric if (IsPointer) { 51890b57cec5SDimitry Andric // Ensure that buffer has a pointer type. 51900b57cec5SDimitry Andric unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex(); 51910b57cec5SDimitry Andric if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) || 51920b57cec5SDimitry Andric !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType()) 51930b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL << 0; 51940b57cec5SDimitry Andric } 51950b57cec5SDimitry Andric 51960b57cec5SDimitry Andric D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr( 5197a7dea167SDimitry Andric S.Context, AL, AL.getArgAsIdent(0)->Ident, ArgumentIdx, TypeTagIdx, 5198a7dea167SDimitry Andric IsPointer)); 51990b57cec5SDimitry Andric } 52000b57cec5SDimitry Andric 52010b57cec5SDimitry Andric static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, 52020b57cec5SDimitry Andric const ParsedAttr &AL) { 52030b57cec5SDimitry Andric if (!AL.isArgIdent(0)) { 52040b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 52050b57cec5SDimitry Andric << AL << 1 << AANT_ArgumentIdentifier; 52060b57cec5SDimitry Andric return; 52070b57cec5SDimitry Andric } 52080b57cec5SDimitry Andric 5209fe6060f1SDimitry Andric if (!AL.checkExactlyNumArgs(S, 1)) 52100b57cec5SDimitry Andric return; 52110b57cec5SDimitry Andric 52120b57cec5SDimitry Andric if (!isa<VarDecl>(D)) { 52130b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type) 521406c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() << ExpectedVariable; 52150b57cec5SDimitry Andric return; 52160b57cec5SDimitry Andric } 52170b57cec5SDimitry Andric 52180b57cec5SDimitry Andric IdentifierInfo *PointerKind = AL.getArgAsIdent(0)->Ident; 52190b57cec5SDimitry Andric TypeSourceInfo *MatchingCTypeLoc = nullptr; 52200b57cec5SDimitry Andric S.GetTypeFromParser(AL.getMatchingCType(), &MatchingCTypeLoc); 52210b57cec5SDimitry Andric assert(MatchingCTypeLoc && "no type source info for attribute argument"); 52220b57cec5SDimitry Andric 5223a7dea167SDimitry Andric D->addAttr(::new (S.Context) TypeTagForDatatypeAttr( 5224a7dea167SDimitry Andric S.Context, AL, PointerKind, MatchingCTypeLoc, AL.getLayoutCompatible(), 5225a7dea167SDimitry Andric AL.getMustBeNull())); 52260b57cec5SDimitry Andric } 52270b57cec5SDimitry Andric 52280b57cec5SDimitry Andric static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 52290b57cec5SDimitry Andric ParamIdx ArgCount; 52300b57cec5SDimitry Andric 52310fca6ea1SDimitry Andric if (!S.checkFunctionOrMethodParameterIndex(D, AL, 1, AL.getArgAsExpr(0), 52320b57cec5SDimitry Andric ArgCount, 52330b57cec5SDimitry Andric true /* CanIndexImplicitThis */)) 52340b57cec5SDimitry Andric return; 52350b57cec5SDimitry Andric 52360b57cec5SDimitry Andric // ArgCount isn't a parameter index [0;n), it's a count [1;n] 5237a7dea167SDimitry Andric D->addAttr(::new (S.Context) 5238a7dea167SDimitry Andric XRayLogArgsAttr(S.Context, AL, ArgCount.getSourceIndex())); 52390b57cec5SDimitry Andric } 52400b57cec5SDimitry Andric 5241480093f4SDimitry Andric static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D, 5242480093f4SDimitry Andric const ParsedAttr &AL) { 52430fca6ea1SDimitry Andric if (S.Context.getTargetInfo().getTriple().isOSAIX()) { 52440fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_aix_attr_unsupported) << AL; 52450fca6ea1SDimitry Andric return; 52460fca6ea1SDimitry Andric } 5247480093f4SDimitry Andric uint32_t Count = 0, Offset = 0; 52480fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, AL.getArgAsExpr(0), Count, 0, true)) 5249480093f4SDimitry Andric return; 5250480093f4SDimitry Andric if (AL.getNumArgs() == 2) { 5251480093f4SDimitry Andric Expr *Arg = AL.getArgAsExpr(1); 52520fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, Arg, Offset, 1, true)) 5253480093f4SDimitry Andric return; 525455e4f9d5SDimitry Andric if (Count < Offset) { 52550fca6ea1SDimitry Andric S.Diag(S.getAttrLoc(AL), diag::err_attribute_argument_out_of_range) 525655e4f9d5SDimitry Andric << &AL << 0 << Count << Arg->getBeginLoc(); 5257480093f4SDimitry Andric return; 5258480093f4SDimitry Andric } 5259480093f4SDimitry Andric } 5260480093f4SDimitry Andric D->addAttr(::new (S.Context) 5261480093f4SDimitry Andric PatchableFunctionEntryAttr(S.Context, AL, Count, Offset)); 5262480093f4SDimitry Andric } 5263480093f4SDimitry Andric 52640fca6ea1SDimitry Andric static void handleBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 5265fe6060f1SDimitry Andric if (!AL.isArgIdent(0)) { 5266fe6060f1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 5267fe6060f1SDimitry Andric << AL << 1 << AANT_ArgumentIdentifier; 5268fe6060f1SDimitry Andric return; 5269fe6060f1SDimitry Andric } 5270fe6060f1SDimitry Andric 5271fe6060f1SDimitry Andric IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident; 5272fe6060f1SDimitry Andric unsigned BuiltinID = Ident->getBuiltinID(); 5273fe6060f1SDimitry Andric StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName(); 5274fe6060f1SDimitry Andric 5275fe6060f1SDimitry Andric bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64(); 5276fe6060f1SDimitry Andric bool IsARM = S.Context.getTargetInfo().getTriple().isARM(); 5277fe6060f1SDimitry Andric bool IsRISCV = S.Context.getTargetInfo().getTriple().isRISCV(); 527881ad6265SDimitry Andric bool IsHLSL = S.Context.getLangOpts().HLSL; 52790fca6ea1SDimitry Andric if ((IsAArch64 && !S.ARM().SveAliasValid(BuiltinID, AliasName)) || 52800fca6ea1SDimitry Andric (IsARM && !S.ARM().MveAliasValid(BuiltinID, AliasName) && 52810fca6ea1SDimitry Andric !S.ARM().CdeAliasValid(BuiltinID, AliasName)) || 52820fca6ea1SDimitry Andric (IsRISCV && !S.RISCV().isAliasValid(BuiltinID, AliasName)) || 528381ad6265SDimitry Andric (!IsAArch64 && !IsARM && !IsRISCV && !IsHLSL)) { 5284fe6060f1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_builtin_alias) << AL; 5285fe6060f1SDimitry Andric return; 5286fe6060f1SDimitry Andric } 5287fe6060f1SDimitry Andric 5288fe6060f1SDimitry Andric D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident)); 5289fe6060f1SDimitry Andric } 5290fe6060f1SDimitry Andric 52910fca6ea1SDimitry Andric static void handleNullableTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 52920fca6ea1SDimitry Andric if (AL.isUsedAsTypeAttr()) 52930fca6ea1SDimitry Andric return; 52940fca6ea1SDimitry Andric 52950fca6ea1SDimitry Andric if (auto *CRD = dyn_cast<CXXRecordDecl>(D); 52960fca6ea1SDimitry Andric !CRD || !(CRD->isClass() || CRD->isStruct())) { 52970fca6ea1SDimitry Andric S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type_str) 52980fca6ea1SDimitry Andric << AL << AL.isRegularKeywordAttribute() << "classes"; 52990fca6ea1SDimitry Andric return; 53000fca6ea1SDimitry Andric } 53010fca6ea1SDimitry Andric 53020fca6ea1SDimitry Andric handleSimpleAttribute<TypeNullableAttr>(S, D, AL); 53030fca6ea1SDimitry Andric } 53040fca6ea1SDimitry Andric 53055f757f3fSDimitry Andric static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 53065f757f3fSDimitry Andric if (!AL.hasParsedType()) { 53075f757f3fSDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; 53085f757f3fSDimitry Andric return; 53095f757f3fSDimitry Andric } 53105f757f3fSDimitry Andric 53115f757f3fSDimitry Andric TypeSourceInfo *ParmTSI = nullptr; 53125f757f3fSDimitry Andric QualType QT = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI); 53135f757f3fSDimitry Andric assert(ParmTSI && "no type source info for attribute argument"); 53145f757f3fSDimitry Andric S.RequireCompleteType(ParmTSI->getTypeLoc().getBeginLoc(), QT, 53155f757f3fSDimitry Andric diag::err_incomplete_type); 53165f757f3fSDimitry Andric 53175f757f3fSDimitry Andric D->addAttr(::new (S.Context) PreferredTypeAttr(S.Context, AL, ParmTSI)); 53185f757f3fSDimitry Andric } 53195f757f3fSDimitry Andric 53200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 53210b57cec5SDimitry Andric // Microsoft specific attribute handlers. 53220b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 53230b57cec5SDimitry Andric 5324a7dea167SDimitry Andric UuidAttr *Sema::mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI, 53255ffd83dbSDimitry Andric StringRef UuidAsWritten, MSGuidDecl *GuidDecl) { 53260b57cec5SDimitry Andric if (const auto *UA = D->getAttr<UuidAttr>()) { 53275ffd83dbSDimitry Andric if (declaresSameEntity(UA->getGuidDecl(), GuidDecl)) 53280b57cec5SDimitry Andric return nullptr; 5329480093f4SDimitry Andric if (!UA->getGuid().empty()) { 53300b57cec5SDimitry Andric Diag(UA->getLocation(), diag::err_mismatched_uuid); 5331a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_previous_uuid); 53320b57cec5SDimitry Andric D->dropAttr<UuidAttr>(); 53330b57cec5SDimitry Andric } 5334480093f4SDimitry Andric } 53350b57cec5SDimitry Andric 53365ffd83dbSDimitry Andric return ::new (Context) UuidAttr(Context, CI, UuidAsWritten, GuidDecl); 53370b57cec5SDimitry Andric } 53380b57cec5SDimitry Andric 53390b57cec5SDimitry Andric static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 53400b57cec5SDimitry Andric if (!S.LangOpts.CPlusPlus) { 53410b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) 53420b57cec5SDimitry Andric << AL << AttributeLangSupport::C; 53430b57cec5SDimitry Andric return; 53440b57cec5SDimitry Andric } 53450b57cec5SDimitry Andric 53465ffd83dbSDimitry Andric StringRef OrigStrRef; 53470b57cec5SDimitry Andric SourceLocation LiteralLoc; 53485ffd83dbSDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, OrigStrRef, &LiteralLoc)) 53490b57cec5SDimitry Andric return; 53500b57cec5SDimitry Andric 53510b57cec5SDimitry Andric // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or 53520b57cec5SDimitry Andric // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former. 53535ffd83dbSDimitry Andric StringRef StrRef = OrigStrRef; 53540b57cec5SDimitry Andric if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}') 53550b57cec5SDimitry Andric StrRef = StrRef.drop_front().drop_back(); 53560b57cec5SDimitry Andric 53570b57cec5SDimitry Andric // Validate GUID length. 53580b57cec5SDimitry Andric if (StrRef.size() != 36) { 53590b57cec5SDimitry Andric S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 53600b57cec5SDimitry Andric return; 53610b57cec5SDimitry Andric } 53620b57cec5SDimitry Andric 53630b57cec5SDimitry Andric for (unsigned i = 0; i < 36; ++i) { 53640b57cec5SDimitry Andric if (i == 8 || i == 13 || i == 18 || i == 23) { 53650b57cec5SDimitry Andric if (StrRef[i] != '-') { 53660b57cec5SDimitry Andric S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 53670b57cec5SDimitry Andric return; 53680b57cec5SDimitry Andric } 53690b57cec5SDimitry Andric } else if (!isHexDigit(StrRef[i])) { 53700b57cec5SDimitry Andric S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 53710b57cec5SDimitry Andric return; 53720b57cec5SDimitry Andric } 53730b57cec5SDimitry Andric } 53740b57cec5SDimitry Andric 53755ffd83dbSDimitry Andric // Convert to our parsed format and canonicalize. 53765ffd83dbSDimitry Andric MSGuidDecl::Parts Parsed; 53775ffd83dbSDimitry Andric StrRef.substr(0, 8).getAsInteger(16, Parsed.Part1); 53785ffd83dbSDimitry Andric StrRef.substr(9, 4).getAsInteger(16, Parsed.Part2); 53795ffd83dbSDimitry Andric StrRef.substr(14, 4).getAsInteger(16, Parsed.Part3); 53805ffd83dbSDimitry Andric for (unsigned i = 0; i != 8; ++i) 53815ffd83dbSDimitry Andric StrRef.substr(19 + 2 * i + (i >= 2 ? 1 : 0), 2) 53825ffd83dbSDimitry Andric .getAsInteger(16, Parsed.Part4And5[i]); 53835ffd83dbSDimitry Andric MSGuidDecl *Guid = S.Context.getMSGuidDecl(Parsed); 53845ffd83dbSDimitry Andric 53850b57cec5SDimitry Andric // FIXME: It'd be nice to also emit a fixit removing uuid(...) (and, if it's 53860b57cec5SDimitry Andric // the only thing in the [] list, the [] too), and add an insertion of 53870b57cec5SDimitry Andric // __declspec(uuid(...)). But sadly, neither the SourceLocs of the commas 53880b57cec5SDimitry Andric // separating attributes nor of the [ and the ] are in the AST. 53890b57cec5SDimitry Andric // Cf "SourceLocations of attribute list delimiters - [[ ... , ... ]] etc" 53900b57cec5SDimitry Andric // on cfe-dev. 53910b57cec5SDimitry Andric if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling. 53920b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated); 53930b57cec5SDimitry Andric 53945ffd83dbSDimitry Andric UuidAttr *UA = S.mergeUuidAttr(D, AL, OrigStrRef, Guid); 53950b57cec5SDimitry Andric if (UA) 53960b57cec5SDimitry Andric D->addAttr(UA); 53970b57cec5SDimitry Andric } 53980b57cec5SDimitry Andric 53990b57cec5SDimitry Andric static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 54000b57cec5SDimitry Andric if (!S.LangOpts.CPlusPlus) { 54010b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) 54020b57cec5SDimitry Andric << AL << AttributeLangSupport::C; 54030b57cec5SDimitry Andric return; 54040b57cec5SDimitry Andric } 54050b57cec5SDimitry Andric MSInheritanceAttr *IA = S.mergeMSInheritanceAttr( 5406480093f4SDimitry Andric D, AL, /*BestCase=*/true, (MSInheritanceModel)AL.getSemanticSpelling()); 54070b57cec5SDimitry Andric if (IA) { 54080b57cec5SDimitry Andric D->addAttr(IA); 54090b57cec5SDimitry Andric S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D)); 54100b57cec5SDimitry Andric } 54110b57cec5SDimitry Andric } 54120b57cec5SDimitry Andric 54130b57cec5SDimitry Andric static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 54140b57cec5SDimitry Andric const auto *VD = cast<VarDecl>(D); 54150b57cec5SDimitry Andric if (!S.Context.getTargetInfo().isTLSSupported()) { 54160b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_thread_unsupported); 54170b57cec5SDimitry Andric return; 54180b57cec5SDimitry Andric } 54190b57cec5SDimitry Andric if (VD->getTSCSpec() != TSCS_unspecified) { 54200b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_declspec_thread_on_thread_variable); 54210b57cec5SDimitry Andric return; 54220b57cec5SDimitry Andric } 54230b57cec5SDimitry Andric if (VD->hasLocalStorage()) { 54240b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_thread_non_global) << "__declspec(thread)"; 54250b57cec5SDimitry Andric return; 54260b57cec5SDimitry Andric } 5427a7dea167SDimitry Andric D->addAttr(::new (S.Context) ThreadAttr(S.Context, AL)); 54280b57cec5SDimitry Andric } 54290b57cec5SDimitry Andric 54305f757f3fSDimitry Andric static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 54315f757f3fSDimitry Andric if (!S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2022_3)) { 54325f757f3fSDimitry Andric S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) 54335f757f3fSDimitry Andric << AL << AL.getRange(); 54345f757f3fSDimitry Andric return; 54355f757f3fSDimitry Andric } 54365f757f3fSDimitry Andric auto *FD = cast<FunctionDecl>(D); 54375f757f3fSDimitry Andric if (FD->isConstexprSpecified() || FD->isConsteval()) { 54385f757f3fSDimitry Andric S.Diag(AL.getLoc(), diag::err_ms_constexpr_cannot_be_applied) 54395f757f3fSDimitry Andric << FD->isConsteval() << FD; 54405f757f3fSDimitry Andric return; 54415f757f3fSDimitry Andric } 54425f757f3fSDimitry Andric if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 54435f757f3fSDimitry Andric if (!S.getLangOpts().CPlusPlus20 && MD->isVirtual()) { 54445f757f3fSDimitry Andric S.Diag(AL.getLoc(), diag::err_ms_constexpr_cannot_be_applied) 54455f757f3fSDimitry Andric << /*virtual*/ 2 << MD; 54465f757f3fSDimitry Andric return; 54475f757f3fSDimitry Andric } 54485f757f3fSDimitry Andric } 54495f757f3fSDimitry Andric D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL)); 54505f757f3fSDimitry Andric } 54515f757f3fSDimitry Andric 54520b57cec5SDimitry Andric static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 54530b57cec5SDimitry Andric SmallVector<StringRef, 4> Tags; 54540b57cec5SDimitry Andric for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { 54550b57cec5SDimitry Andric StringRef Tag; 54560b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, I, Tag)) 54570b57cec5SDimitry Andric return; 54580b57cec5SDimitry Andric Tags.push_back(Tag); 54590b57cec5SDimitry Andric } 54600b57cec5SDimitry Andric 54610b57cec5SDimitry Andric if (const auto *NS = dyn_cast<NamespaceDecl>(D)) { 54620b57cec5SDimitry Andric if (!NS->isInline()) { 54630b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 0; 54640b57cec5SDimitry Andric return; 54650b57cec5SDimitry Andric } 54660b57cec5SDimitry Andric if (NS->isAnonymousNamespace()) { 54670b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 1; 54680b57cec5SDimitry Andric return; 54690b57cec5SDimitry Andric } 54700b57cec5SDimitry Andric if (AL.getNumArgs() == 0) 54710b57cec5SDimitry Andric Tags.push_back(NS->getName()); 5472fe6060f1SDimitry Andric } else if (!AL.checkAtLeastNumArgs(S, 1)) 54730b57cec5SDimitry Andric return; 54740b57cec5SDimitry Andric 54750b57cec5SDimitry Andric // Store tags sorted and without duplicates. 54760b57cec5SDimitry Andric llvm::sort(Tags); 54770b57cec5SDimitry Andric Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end()); 54780b57cec5SDimitry Andric 54790b57cec5SDimitry Andric D->addAttr(::new (S.Context) 5480a7dea167SDimitry Andric AbiTagAttr(S.Context, AL, Tags.data(), Tags.size())); 54810b57cec5SDimitry Andric } 54820b57cec5SDimitry Andric 5483349cc55cSDimitry Andric static bool hasBTFDeclTagAttr(Decl *D, StringRef Tag) { 5484349cc55cSDimitry Andric for (const auto *I : D->specific_attrs<BTFDeclTagAttr>()) { 5485349cc55cSDimitry Andric if (I->getBTFDeclTag() == Tag) 5486349cc55cSDimitry Andric return true; 5487349cc55cSDimitry Andric } 5488349cc55cSDimitry Andric return false; 5489349cc55cSDimitry Andric } 5490349cc55cSDimitry Andric 5491349cc55cSDimitry Andric static void handleBTFDeclTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 5492349cc55cSDimitry Andric StringRef Str; 5493349cc55cSDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) 5494349cc55cSDimitry Andric return; 5495349cc55cSDimitry Andric if (hasBTFDeclTagAttr(D, Str)) 5496349cc55cSDimitry Andric return; 5497349cc55cSDimitry Andric 5498349cc55cSDimitry Andric D->addAttr(::new (S.Context) BTFDeclTagAttr(S.Context, AL, Str)); 5499349cc55cSDimitry Andric } 5500349cc55cSDimitry Andric 5501349cc55cSDimitry Andric BTFDeclTagAttr *Sema::mergeBTFDeclTagAttr(Decl *D, const BTFDeclTagAttr &AL) { 5502349cc55cSDimitry Andric if (hasBTFDeclTagAttr(D, AL.getBTFDeclTag())) 5503349cc55cSDimitry Andric return nullptr; 5504349cc55cSDimitry Andric return ::new (Context) BTFDeclTagAttr(Context, AL, AL.getBTFDeclTag()); 5505349cc55cSDimitry Andric } 5506349cc55cSDimitry Andric 55070b57cec5SDimitry Andric static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 55080b57cec5SDimitry Andric // Dispatch the interrupt attribute based on the current target. 55090b57cec5SDimitry Andric switch (S.Context.getTargetInfo().getTriple().getArch()) { 55100b57cec5SDimitry Andric case llvm::Triple::msp430: 55110fca6ea1SDimitry Andric S.MSP430().handleInterruptAttr(D, AL); 55120b57cec5SDimitry Andric break; 55130b57cec5SDimitry Andric case llvm::Triple::mipsel: 55140b57cec5SDimitry Andric case llvm::Triple::mips: 55150fca6ea1SDimitry Andric S.MIPS().handleInterruptAttr(D, AL); 55160b57cec5SDimitry Andric break; 5517fe6060f1SDimitry Andric case llvm::Triple::m68k: 55180fca6ea1SDimitry Andric S.M68k().handleInterruptAttr(D, AL); 5519fe6060f1SDimitry Andric break; 55200b57cec5SDimitry Andric case llvm::Triple::x86: 55210b57cec5SDimitry Andric case llvm::Triple::x86_64: 55220fca6ea1SDimitry Andric S.X86().handleAnyInterruptAttr(D, AL); 55230b57cec5SDimitry Andric break; 55240b57cec5SDimitry Andric case llvm::Triple::avr: 55250fca6ea1SDimitry Andric S.AVR().handleInterruptAttr(D, AL); 55260b57cec5SDimitry Andric break; 55270b57cec5SDimitry Andric case llvm::Triple::riscv32: 55280b57cec5SDimitry Andric case llvm::Triple::riscv64: 55290fca6ea1SDimitry Andric S.RISCV().handleInterruptAttr(D, AL); 55300b57cec5SDimitry Andric break; 55310b57cec5SDimitry Andric default: 55320fca6ea1SDimitry Andric S.ARM().handleInterruptAttr(D, AL); 55330b57cec5SDimitry Andric break; 55340b57cec5SDimitry Andric } 55350b57cec5SDimitry Andric } 55360b57cec5SDimitry Andric 55370b57cec5SDimitry Andric static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) { 55380b57cec5SDimitry Andric uint32_t Version; 55390b57cec5SDimitry Andric Expr *VersionExpr = static_cast<Expr *>(AL.getArgAsExpr(0)); 55400fca6ea1SDimitry Andric if (!S.checkUInt32Argument(AL, AL.getArgAsExpr(0), Version)) 55410b57cec5SDimitry Andric return; 55420b57cec5SDimitry Andric 55430b57cec5SDimitry Andric // TODO: Investigate what happens with the next major version of MSVC. 55440b57cec5SDimitry Andric if (Version != LangOptions::MSVC2015 / 100) { 55450b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) 55460b57cec5SDimitry Andric << AL << Version << VersionExpr->getSourceRange(); 55470b57cec5SDimitry Andric return; 55480b57cec5SDimitry Andric } 55490b57cec5SDimitry Andric 55500b57cec5SDimitry Andric // The attribute expects a "major" version number like 19, but new versions of 55510b57cec5SDimitry Andric // MSVC have moved to updating the "minor", or less significant numbers, so we 55520b57cec5SDimitry Andric // have to multiply by 100 now. 55530b57cec5SDimitry Andric Version *= 100; 55540b57cec5SDimitry Andric 5555a7dea167SDimitry Andric D->addAttr(::new (S.Context) LayoutVersionAttr(S.Context, AL, Version)); 55560b57cec5SDimitry Andric } 55570b57cec5SDimitry Andric 5558a7dea167SDimitry Andric DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, 5559a7dea167SDimitry Andric const AttributeCommonInfo &CI) { 55600b57cec5SDimitry Andric if (D->hasAttr<DLLExportAttr>()) { 5561a7dea167SDimitry Andric Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'dllimport'"; 55620b57cec5SDimitry Andric return nullptr; 55630b57cec5SDimitry Andric } 55640b57cec5SDimitry Andric 55650b57cec5SDimitry Andric if (D->hasAttr<DLLImportAttr>()) 55660b57cec5SDimitry Andric return nullptr; 55670b57cec5SDimitry Andric 5568a7dea167SDimitry Andric return ::new (Context) DLLImportAttr(Context, CI); 55690b57cec5SDimitry Andric } 55700b57cec5SDimitry Andric 5571a7dea167SDimitry Andric DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, 5572a7dea167SDimitry Andric const AttributeCommonInfo &CI) { 55730b57cec5SDimitry Andric if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) { 55740b57cec5SDimitry Andric Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import; 55750b57cec5SDimitry Andric D->dropAttr<DLLImportAttr>(); 55760b57cec5SDimitry Andric } 55770b57cec5SDimitry Andric 55780b57cec5SDimitry Andric if (D->hasAttr<DLLExportAttr>()) 55790b57cec5SDimitry Andric return nullptr; 55800b57cec5SDimitry Andric 5581a7dea167SDimitry Andric return ::new (Context) DLLExportAttr(Context, CI); 55820b57cec5SDimitry Andric } 55830b57cec5SDimitry Andric 55840b57cec5SDimitry Andric static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { 55850b57cec5SDimitry Andric if (isa<ClassTemplatePartialSpecializationDecl>(D) && 5586e8d8bef9SDimitry Andric (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { 55870b57cec5SDimitry Andric S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; 55880b57cec5SDimitry Andric return; 55890b57cec5SDimitry Andric } 55900b57cec5SDimitry Andric 55910b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 55920b57cec5SDimitry Andric if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && 5593e8d8bef9SDimitry Andric !(S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { 55940b57cec5SDimitry Andric // MinGW doesn't allow dllimport on inline functions. 55950b57cec5SDimitry Andric S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) 55960b57cec5SDimitry Andric << A; 55970b57cec5SDimitry Andric return; 55980b57cec5SDimitry Andric } 55990b57cec5SDimitry Andric } 56000b57cec5SDimitry Andric 56010b57cec5SDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { 5602e8d8bef9SDimitry Andric if ((S.Context.getTargetInfo().shouldDLLImportComdatSymbols()) && 56030b57cec5SDimitry Andric MD->getParent()->isLambda()) { 56040b57cec5SDimitry Andric S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A; 56050b57cec5SDimitry Andric return; 56060b57cec5SDimitry Andric } 56070b57cec5SDimitry Andric } 56080b57cec5SDimitry Andric 56090b57cec5SDimitry Andric Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport 5610a7dea167SDimitry Andric ? (Attr *)S.mergeDLLExportAttr(D, A) 5611a7dea167SDimitry Andric : (Attr *)S.mergeDLLImportAttr(D, A); 56120b57cec5SDimitry Andric if (NewAttr) 56130b57cec5SDimitry Andric D->addAttr(NewAttr); 56140b57cec5SDimitry Andric } 56150b57cec5SDimitry Andric 56160b57cec5SDimitry Andric MSInheritanceAttr * 5617a7dea167SDimitry Andric Sema::mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI, 5618a7dea167SDimitry Andric bool BestCase, 5619480093f4SDimitry Andric MSInheritanceModel Model) { 56200b57cec5SDimitry Andric if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) { 5621480093f4SDimitry Andric if (IA->getInheritanceModel() == Model) 56220b57cec5SDimitry Andric return nullptr; 56230b57cec5SDimitry Andric Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance) 56240b57cec5SDimitry Andric << 1 /*previous declaration*/; 5625a7dea167SDimitry Andric Diag(CI.getLoc(), diag::note_previous_ms_inheritance); 56260b57cec5SDimitry Andric D->dropAttr<MSInheritanceAttr>(); 56270b57cec5SDimitry Andric } 56280b57cec5SDimitry Andric 56290b57cec5SDimitry Andric auto *RD = cast<CXXRecordDecl>(D); 56300b57cec5SDimitry Andric if (RD->hasDefinition()) { 5631a7dea167SDimitry Andric if (checkMSInheritanceAttrOnDefinition(RD, CI.getRange(), BestCase, 5632480093f4SDimitry Andric Model)) { 56330b57cec5SDimitry Andric return nullptr; 56340b57cec5SDimitry Andric } 56350b57cec5SDimitry Andric } else { 56360b57cec5SDimitry Andric if (isa<ClassTemplatePartialSpecializationDecl>(RD)) { 5637a7dea167SDimitry Andric Diag(CI.getLoc(), diag::warn_ignored_ms_inheritance) 56380b57cec5SDimitry Andric << 1 /*partial specialization*/; 56390b57cec5SDimitry Andric return nullptr; 56400b57cec5SDimitry Andric } 56410b57cec5SDimitry Andric if (RD->getDescribedClassTemplate()) { 5642a7dea167SDimitry Andric Diag(CI.getLoc(), diag::warn_ignored_ms_inheritance) 56430b57cec5SDimitry Andric << 0 /*primary template*/; 56440b57cec5SDimitry Andric return nullptr; 56450b57cec5SDimitry Andric } 56460b57cec5SDimitry Andric } 56470b57cec5SDimitry Andric 5648a7dea167SDimitry Andric return ::new (Context) MSInheritanceAttr(Context, CI, BestCase); 56490b57cec5SDimitry Andric } 56500b57cec5SDimitry Andric 56510b57cec5SDimitry Andric static void handleCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 56520b57cec5SDimitry Andric // The capability attributes take a single string parameter for the name of 56530b57cec5SDimitry Andric // the capability they represent. The lockable attribute does not take any 56540b57cec5SDimitry Andric // parameters. However, semantically, both attributes represent the same 56550b57cec5SDimitry Andric // concept, and so they use the same semantic attribute. Eventually, the 56560b57cec5SDimitry Andric // lockable attribute will be removed. 56570b57cec5SDimitry Andric // 56580b57cec5SDimitry Andric // For backward compatibility, any capability which has no specified string 56590b57cec5SDimitry Andric // literal will be considered a "mutex." 56600b57cec5SDimitry Andric StringRef N("mutex"); 56610b57cec5SDimitry Andric SourceLocation LiteralLoc; 56620b57cec5SDimitry Andric if (AL.getKind() == ParsedAttr::AT_Capability && 56630b57cec5SDimitry Andric !S.checkStringLiteralArgumentAttr(AL, 0, N, &LiteralLoc)) 56640b57cec5SDimitry Andric return; 56650b57cec5SDimitry Andric 5666a7dea167SDimitry Andric D->addAttr(::new (S.Context) CapabilityAttr(S.Context, AL, N)); 56670b57cec5SDimitry Andric } 56680b57cec5SDimitry Andric 56690b57cec5SDimitry Andric static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 56700b57cec5SDimitry Andric SmallVector<Expr*, 1> Args; 56710b57cec5SDimitry Andric if (!checkLockFunAttrCommon(S, D, AL, Args)) 56720b57cec5SDimitry Andric return; 56730b57cec5SDimitry Andric 5674a7dea167SDimitry Andric D->addAttr(::new (S.Context) 5675a7dea167SDimitry Andric AssertCapabilityAttr(S.Context, AL, Args.data(), Args.size())); 56760b57cec5SDimitry Andric } 56770b57cec5SDimitry Andric 56780b57cec5SDimitry Andric static void handleAcquireCapabilityAttr(Sema &S, Decl *D, 56790b57cec5SDimitry Andric const ParsedAttr &AL) { 56800b57cec5SDimitry Andric SmallVector<Expr*, 1> Args; 56810b57cec5SDimitry Andric if (!checkLockFunAttrCommon(S, D, AL, Args)) 56820b57cec5SDimitry Andric return; 56830b57cec5SDimitry Andric 5684a7dea167SDimitry Andric D->addAttr(::new (S.Context) AcquireCapabilityAttr(S.Context, AL, Args.data(), 5685a7dea167SDimitry Andric Args.size())); 56860b57cec5SDimitry Andric } 56870b57cec5SDimitry Andric 56880b57cec5SDimitry Andric static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D, 56890b57cec5SDimitry Andric const ParsedAttr &AL) { 56900b57cec5SDimitry Andric SmallVector<Expr*, 2> Args; 56910b57cec5SDimitry Andric if (!checkTryLockFunAttrCommon(S, D, AL, Args)) 56920b57cec5SDimitry Andric return; 56930b57cec5SDimitry Andric 5694a7dea167SDimitry Andric D->addAttr(::new (S.Context) TryAcquireCapabilityAttr( 5695a7dea167SDimitry Andric S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); 56960b57cec5SDimitry Andric } 56970b57cec5SDimitry Andric 56980b57cec5SDimitry Andric static void handleReleaseCapabilityAttr(Sema &S, Decl *D, 56990b57cec5SDimitry Andric const ParsedAttr &AL) { 57000b57cec5SDimitry Andric // Check that all arguments are lockable objects. 57010b57cec5SDimitry Andric SmallVector<Expr *, 1> Args; 57020b57cec5SDimitry Andric checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, true); 57030b57cec5SDimitry Andric 5704a7dea167SDimitry Andric D->addAttr(::new (S.Context) ReleaseCapabilityAttr(S.Context, AL, Args.data(), 5705a7dea167SDimitry Andric Args.size())); 57060b57cec5SDimitry Andric } 57070b57cec5SDimitry Andric 57080b57cec5SDimitry Andric static void handleRequiresCapabilityAttr(Sema &S, Decl *D, 57090b57cec5SDimitry Andric const ParsedAttr &AL) { 5710fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1)) 57110b57cec5SDimitry Andric return; 57120b57cec5SDimitry Andric 57130b57cec5SDimitry Andric // check that all arguments are lockable objects 57140b57cec5SDimitry Andric SmallVector<Expr*, 1> Args; 57150b57cec5SDimitry Andric checkAttrArgsAreCapabilityObjs(S, D, AL, Args); 57160b57cec5SDimitry Andric if (Args.empty()) 57170b57cec5SDimitry Andric return; 57180b57cec5SDimitry Andric 57190b57cec5SDimitry Andric RequiresCapabilityAttr *RCA = ::new (S.Context) 5720a7dea167SDimitry Andric RequiresCapabilityAttr(S.Context, AL, Args.data(), Args.size()); 57210b57cec5SDimitry Andric 57220b57cec5SDimitry Andric D->addAttr(RCA); 57230b57cec5SDimitry Andric } 57240b57cec5SDimitry Andric 57250b57cec5SDimitry Andric static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 57260b57cec5SDimitry Andric if (const auto *NSD = dyn_cast<NamespaceDecl>(D)) { 57270b57cec5SDimitry Andric if (NSD->isAnonymousNamespace()) { 57280b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_deprecated_anonymous_namespace); 57290b57cec5SDimitry Andric // Do not want to attach the attribute to the namespace because that will 57300b57cec5SDimitry Andric // cause confusing diagnostic reports for uses of declarations within the 57310b57cec5SDimitry Andric // namespace. 57320b57cec5SDimitry Andric return; 57330b57cec5SDimitry Andric } 5734fe6060f1SDimitry Andric } else if (isa<UsingDecl, UnresolvedUsingTypenameDecl, 5735fe6060f1SDimitry Andric UnresolvedUsingValueDecl>(D)) { 5736fe6060f1SDimitry Andric S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using) 5737fe6060f1SDimitry Andric << AL; 5738fe6060f1SDimitry Andric return; 57390b57cec5SDimitry Andric } 57400b57cec5SDimitry Andric 57410b57cec5SDimitry Andric // Handle the cases where the attribute has a text message. 57420b57cec5SDimitry Andric StringRef Str, Replacement; 57430b57cec5SDimitry Andric if (AL.isArgExpr(0) && AL.getArgAsExpr(0) && 57440b57cec5SDimitry Andric !S.checkStringLiteralArgumentAttr(AL, 0, Str)) 57450b57cec5SDimitry Andric return; 57460b57cec5SDimitry Andric 5747fe6060f1SDimitry Andric // Support a single optional message only for Declspec and [[]] spellings. 5748fe6060f1SDimitry Andric if (AL.isDeclspecAttribute() || AL.isStandardAttributeSyntax()) 5749fe6060f1SDimitry Andric AL.checkAtMostNumArgs(S, 1); 57500b57cec5SDimitry Andric else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) && 57510b57cec5SDimitry Andric !S.checkStringLiteralArgumentAttr(AL, 1, Replacement)) 57520b57cec5SDimitry Andric return; 57530b57cec5SDimitry Andric 57540b57cec5SDimitry Andric if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope()) 57550b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL; 57560b57cec5SDimitry Andric 5757a7dea167SDimitry Andric D->addAttr(::new (S.Context) DeprecatedAttr(S.Context, AL, Str, Replacement)); 57580b57cec5SDimitry Andric } 57590b57cec5SDimitry Andric 57600b57cec5SDimitry Andric static bool isGlobalVar(const Decl *D) { 57610b57cec5SDimitry Andric if (const auto *S = dyn_cast<VarDecl>(D)) 57620b57cec5SDimitry Andric return S->hasGlobalStorage(); 57630b57cec5SDimitry Andric return false; 57640b57cec5SDimitry Andric } 57650b57cec5SDimitry Andric 576681ad6265SDimitry Andric static bool isSanitizerAttributeAllowedOnGlobals(StringRef Sanitizer) { 576781ad6265SDimitry Andric return Sanitizer == "address" || Sanitizer == "hwaddress" || 576881ad6265SDimitry Andric Sanitizer == "memtag"; 576981ad6265SDimitry Andric } 577081ad6265SDimitry Andric 57710b57cec5SDimitry Andric static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 5772fe6060f1SDimitry Andric if (!AL.checkAtLeastNumArgs(S, 1)) 57730b57cec5SDimitry Andric return; 57740b57cec5SDimitry Andric 57750b57cec5SDimitry Andric std::vector<StringRef> Sanitizers; 57760b57cec5SDimitry Andric 57770b57cec5SDimitry Andric for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { 57780b57cec5SDimitry Andric StringRef SanitizerName; 57790b57cec5SDimitry Andric SourceLocation LiteralLoc; 57800b57cec5SDimitry Andric 57810b57cec5SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, I, SanitizerName, &LiteralLoc)) 57820b57cec5SDimitry Andric return; 57830b57cec5SDimitry Andric 57840b57cec5SDimitry Andric if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == 5785fe6060f1SDimitry Andric SanitizerMask() && 5786fe6060f1SDimitry Andric SanitizerName != "coverage") 57870b57cec5SDimitry Andric S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName; 578881ad6265SDimitry Andric else if (isGlobalVar(D) && !isSanitizerAttributeAllowedOnGlobals(SanitizerName)) 5789bdd1243dSDimitry Andric S.Diag(D->getLocation(), diag::warn_attribute_type_not_supported_global) 5790bdd1243dSDimitry Andric << AL << SanitizerName; 57910b57cec5SDimitry Andric Sanitizers.push_back(SanitizerName); 57920b57cec5SDimitry Andric } 57930b57cec5SDimitry Andric 5794a7dea167SDimitry Andric D->addAttr(::new (S.Context) NoSanitizeAttr(S.Context, AL, Sanitizers.data(), 5795a7dea167SDimitry Andric Sanitizers.size())); 57960b57cec5SDimitry Andric } 57970b57cec5SDimitry Andric 57980b57cec5SDimitry Andric static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, 57990b57cec5SDimitry Andric const ParsedAttr &AL) { 5800a7dea167SDimitry Andric StringRef AttrName = AL.getAttrName()->getName(); 58010b57cec5SDimitry Andric normalizeName(AttrName); 58020b57cec5SDimitry Andric StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName) 58030b57cec5SDimitry Andric .Case("no_address_safety_analysis", "address") 58040b57cec5SDimitry Andric .Case("no_sanitize_address", "address") 58050b57cec5SDimitry Andric .Case("no_sanitize_thread", "thread") 58060b57cec5SDimitry Andric .Case("no_sanitize_memory", "memory"); 58070b57cec5SDimitry Andric if (isGlobalVar(D) && SanitizerName != "address") 58080b57cec5SDimitry Andric S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) 580906c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() << ExpectedFunction; 58100b57cec5SDimitry Andric 58110b57cec5SDimitry Andric // FIXME: Rather than create a NoSanitizeSpecificAttr, this creates a 58120b57cec5SDimitry Andric // NoSanitizeAttr object; but we need to calculate the correct spelling list 58130b57cec5SDimitry Andric // index rather than incorrectly assume the index for NoSanitizeSpecificAttr 58140b57cec5SDimitry Andric // has the same spellings as the index for NoSanitizeAttr. We don't have a 58150b57cec5SDimitry Andric // general way to "translate" between the two, so this hack attempts to work 5816349cc55cSDimitry Andric // around the issue with hard-coded indices. This is critical for calling 58170b57cec5SDimitry Andric // getSpelling() or prettyPrint() on the resulting semantic attribute object 58180b57cec5SDimitry Andric // without failing assertions. 58190b57cec5SDimitry Andric unsigned TranslatedSpellingIndex = 0; 5820fe6060f1SDimitry Andric if (AL.isStandardAttributeSyntax()) 58210b57cec5SDimitry Andric TranslatedSpellingIndex = 1; 58220b57cec5SDimitry Andric 5823a7dea167SDimitry Andric AttributeCommonInfo Info = AL; 5824a7dea167SDimitry Andric Info.setAttributeSpellingListIndex(TranslatedSpellingIndex); 5825a7dea167SDimitry Andric D->addAttr(::new (S.Context) 5826a7dea167SDimitry Andric NoSanitizeAttr(S.Context, Info, &SanitizerName, 1)); 58270b57cec5SDimitry Andric } 58280b57cec5SDimitry Andric 58290b57cec5SDimitry Andric static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 58300b57cec5SDimitry Andric if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr(D, AL)) 58310b57cec5SDimitry Andric D->addAttr(Internal); 58320b57cec5SDimitry Andric } 58330b57cec5SDimitry Andric 583481ad6265SDimitry Andric static void handleZeroCallUsedRegsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 583581ad6265SDimitry Andric // Check that the argument is a string literal. 583681ad6265SDimitry Andric StringRef KindStr; 583781ad6265SDimitry Andric SourceLocation LiteralLoc; 583881ad6265SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, KindStr, &LiteralLoc)) 583981ad6265SDimitry Andric return; 584081ad6265SDimitry Andric 584181ad6265SDimitry Andric ZeroCallUsedRegsAttr::ZeroCallUsedRegsKind Kind; 584281ad6265SDimitry Andric if (!ZeroCallUsedRegsAttr::ConvertStrToZeroCallUsedRegsKind(KindStr, Kind)) { 584381ad6265SDimitry Andric S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) 584481ad6265SDimitry Andric << AL << KindStr; 584581ad6265SDimitry Andric return; 584681ad6265SDimitry Andric } 584781ad6265SDimitry Andric 584881ad6265SDimitry Andric D->dropAttr<ZeroCallUsedRegsAttr>(); 584981ad6265SDimitry Andric D->addAttr(ZeroCallUsedRegsAttr::Create(S.Context, Kind, AL)); 585081ad6265SDimitry Andric } 585181ad6265SDimitry Andric 58520fca6ea1SDimitry Andric static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL) { 58530fca6ea1SDimitry Andric auto *FD = dyn_cast<FieldDecl>(D); 58540fca6ea1SDimitry Andric assert(FD); 58550fca6ea1SDimitry Andric 58560fca6ea1SDimitry Andric auto *CountExpr = AL.getArgAsExpr(0); 58570fca6ea1SDimitry Andric if (!CountExpr) 5858297eecfbSDimitry Andric return; 5859297eecfbSDimitry Andric 58600fca6ea1SDimitry Andric bool CountInBytes; 58610fca6ea1SDimitry Andric bool OrNull; 58620fca6ea1SDimitry Andric switch (AL.getKind()) { 58630fca6ea1SDimitry Andric case ParsedAttr::AT_CountedBy: 58640fca6ea1SDimitry Andric CountInBytes = false; 58650fca6ea1SDimitry Andric OrNull = false; 5866297eecfbSDimitry Andric break; 58670fca6ea1SDimitry Andric case ParsedAttr::AT_CountedByOrNull: 58680fca6ea1SDimitry Andric CountInBytes = false; 58690fca6ea1SDimitry Andric OrNull = true; 58700fca6ea1SDimitry Andric break; 58710fca6ea1SDimitry Andric case ParsedAttr::AT_SizedBy: 58720fca6ea1SDimitry Andric CountInBytes = true; 58730fca6ea1SDimitry Andric OrNull = false; 58740fca6ea1SDimitry Andric break; 58750fca6ea1SDimitry Andric case ParsedAttr::AT_SizedByOrNull: 58760fca6ea1SDimitry Andric CountInBytes = true; 58770fca6ea1SDimitry Andric OrNull = true; 58780fca6ea1SDimitry Andric break; 58790fca6ea1SDimitry Andric default: 58800fca6ea1SDimitry Andric llvm_unreachable("unexpected counted_by family attribute"); 5881297eecfbSDimitry Andric } 5882297eecfbSDimitry Andric 58830fca6ea1SDimitry Andric llvm::SmallVector<TypeCoupledDeclRefInfo, 1> Decls; 58840fca6ea1SDimitry Andric if (S.CheckCountedByAttrOnField(FD, CountExpr, Decls, CountInBytes, OrNull)) 58850fca6ea1SDimitry Andric return; 5886297eecfbSDimitry Andric 58870fca6ea1SDimitry Andric QualType CAT = S.BuildCountAttributedArrayOrPointerType( 58880fca6ea1SDimitry Andric FD->getType(), CountExpr, CountInBytes, OrNull); 58890fca6ea1SDimitry Andric FD->setType(CAT); 5890297eecfbSDimitry Andric } 5891297eecfbSDimitry Andric 5892753f127fSDimitry Andric static void handleFunctionReturnThunksAttr(Sema &S, Decl *D, 5893753f127fSDimitry Andric const ParsedAttr &AL) { 5894753f127fSDimitry Andric StringRef KindStr; 5895753f127fSDimitry Andric SourceLocation LiteralLoc; 5896753f127fSDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, KindStr, &LiteralLoc)) 5897753f127fSDimitry Andric return; 5898753f127fSDimitry Andric 5899753f127fSDimitry Andric FunctionReturnThunksAttr::Kind Kind; 5900753f127fSDimitry Andric if (!FunctionReturnThunksAttr::ConvertStrToKind(KindStr, Kind)) { 5901753f127fSDimitry Andric S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) 5902753f127fSDimitry Andric << AL << KindStr; 5903753f127fSDimitry Andric return; 5904753f127fSDimitry Andric } 5905753f127fSDimitry Andric // FIXME: it would be good to better handle attribute merging rather than 5906753f127fSDimitry Andric // silently replacing the existing attribute, so long as it does not break 5907753f127fSDimitry Andric // the expected codegen tests. 5908753f127fSDimitry Andric D->dropAttr<FunctionReturnThunksAttr>(); 5909753f127fSDimitry Andric D->addAttr(FunctionReturnThunksAttr::Create(S.Context, Kind, AL)); 5910753f127fSDimitry Andric } 5911753f127fSDimitry Andric 591206c3fb27SDimitry Andric static void handleAvailableOnlyInDefaultEvalMethod(Sema &S, Decl *D, 591306c3fb27SDimitry Andric const ParsedAttr &AL) { 591406c3fb27SDimitry Andric assert(isa<TypedefNameDecl>(D) && "This attribute only applies to a typedef"); 591506c3fb27SDimitry Andric handleSimpleAttribute<AvailableOnlyInDefaultEvalMethodAttr>(S, D, AL); 591606c3fb27SDimitry Andric } 591706c3fb27SDimitry Andric 591806c3fb27SDimitry Andric static void handleNoMergeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 591906c3fb27SDimitry Andric auto *VDecl = dyn_cast<VarDecl>(D); 592006c3fb27SDimitry Andric if (VDecl && !VDecl->isFunctionPointerType()) { 592106c3fb27SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_ignored_non_function_pointer) 592206c3fb27SDimitry Andric << AL << VDecl; 592306c3fb27SDimitry Andric return; 592406c3fb27SDimitry Andric } 592506c3fb27SDimitry Andric D->addAttr(NoMergeAttr::Create(S.Context, AL)); 592606c3fb27SDimitry Andric } 592706c3fb27SDimitry Andric 59285f757f3fSDimitry Andric static void handleNoUniqueAddressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 59295f757f3fSDimitry Andric D->addAttr(NoUniqueAddressAttr::Create(S.Context, AL)); 59305f757f3fSDimitry Andric } 59315f757f3fSDimitry Andric 59320b57cec5SDimitry Andric static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) { 59330b57cec5SDimitry Andric if (!cast<VarDecl>(D)->hasGlobalStorage()) { 59340b57cec5SDimitry Andric S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var) 59350b57cec5SDimitry Andric << (A.getKind() == ParsedAttr::AT_AlwaysDestroy); 59360b57cec5SDimitry Andric return; 59370b57cec5SDimitry Andric } 59380b57cec5SDimitry Andric 59390b57cec5SDimitry Andric if (A.getKind() == ParsedAttr::AT_AlwaysDestroy) 5940fe6060f1SDimitry Andric handleSimpleAttribute<AlwaysDestroyAttr>(S, D, A); 59410b57cec5SDimitry Andric else 5942fe6060f1SDimitry Andric handleSimpleAttribute<NoDestroyAttr>(S, D, A); 59430b57cec5SDimitry Andric } 59440b57cec5SDimitry Andric 59450b57cec5SDimitry Andric static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 59460b57cec5SDimitry Andric assert(cast<VarDecl>(D)->getStorageDuration() == SD_Automatic && 59470b57cec5SDimitry Andric "uninitialized is only valid on automatic duration variables"); 5948a7dea167SDimitry Andric D->addAttr(::new (S.Context) UninitializedAttr(S.Context, AL)); 59490b57cec5SDimitry Andric } 59500b57cec5SDimitry Andric 59510b57cec5SDimitry Andric static void handleMIGServerRoutineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 59520b57cec5SDimitry Andric // Check that the return type is a `typedef int kern_return_t` or a typedef 59530b57cec5SDimitry Andric // around it, because otherwise MIG convention checks make no sense. 59540b57cec5SDimitry Andric // BlockDecl doesn't store a return type, so it's annoying to check, 59550b57cec5SDimitry Andric // so let's skip it for now. 59560b57cec5SDimitry Andric if (!isa<BlockDecl>(D)) { 59570b57cec5SDimitry Andric QualType T = getFunctionOrMethodResultType(D); 59580b57cec5SDimitry Andric bool IsKernReturnT = false; 59590b57cec5SDimitry Andric while (const auto *TT = T->getAs<TypedefType>()) { 59600b57cec5SDimitry Andric IsKernReturnT = (TT->getDecl()->getName() == "kern_return_t"); 59610b57cec5SDimitry Andric T = TT->desugar(); 59620b57cec5SDimitry Andric } 59630b57cec5SDimitry Andric if (!IsKernReturnT || T.getCanonicalType() != S.getASTContext().IntTy) { 59640b57cec5SDimitry Andric S.Diag(D->getBeginLoc(), 59650b57cec5SDimitry Andric diag::warn_mig_server_routine_does_not_return_kern_return_t); 59660b57cec5SDimitry Andric return; 59670b57cec5SDimitry Andric } 59680b57cec5SDimitry Andric } 59690b57cec5SDimitry Andric 59700b57cec5SDimitry Andric handleSimpleAttribute<MIGServerRoutineAttr>(S, D, AL); 59710b57cec5SDimitry Andric } 59720b57cec5SDimitry Andric 59730b57cec5SDimitry Andric static void handleMSAllocatorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 59740b57cec5SDimitry Andric // Warn if the return type is not a pointer or reference type. 59750b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(D)) { 59760b57cec5SDimitry Andric QualType RetTy = FD->getReturnType(); 59770b57cec5SDimitry Andric if (!RetTy->isPointerType() && !RetTy->isReferenceType()) { 59780b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_declspec_allocator_nonpointer) 59790b57cec5SDimitry Andric << AL.getRange() << RetTy; 59800b57cec5SDimitry Andric return; 59810b57cec5SDimitry Andric } 59820b57cec5SDimitry Andric } 59830b57cec5SDimitry Andric 59840b57cec5SDimitry Andric handleSimpleAttribute<MSAllocatorAttr>(S, D, AL); 59850b57cec5SDimitry Andric } 59860b57cec5SDimitry Andric 59875ffd83dbSDimitry Andric static void handleAcquireHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 5988480093f4SDimitry Andric if (AL.isUsedAsTypeAttr()) 5989480093f4SDimitry Andric return; 5990480093f4SDimitry Andric // Warn if the parameter is definitely not an output parameter. 5991480093f4SDimitry Andric if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { 5992480093f4SDimitry Andric if (PVD->getType()->isIntegerType()) { 5993480093f4SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_output_parameter) 5994480093f4SDimitry Andric << AL.getRange(); 5995480093f4SDimitry Andric return; 5996480093f4SDimitry Andric } 5997480093f4SDimitry Andric } 5998480093f4SDimitry Andric StringRef Argument; 5999480093f4SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) 6000480093f4SDimitry Andric return; 6001480093f4SDimitry Andric D->addAttr(AcquireHandleAttr::Create(S.Context, Argument, AL)); 6002480093f4SDimitry Andric } 6003480093f4SDimitry Andric 6004480093f4SDimitry Andric template<typename Attr> 6005480093f4SDimitry Andric static void handleHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 6006480093f4SDimitry Andric StringRef Argument; 6007480093f4SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) 6008480093f4SDimitry Andric return; 6009480093f4SDimitry Andric D->addAttr(Attr::Create(S.Context, Argument, AL)); 6010480093f4SDimitry Andric } 6011480093f4SDimitry Andric 601206c3fb27SDimitry Andric template<typename Attr> 601306c3fb27SDimitry Andric static void handleUnsafeBufferUsage(Sema &S, Decl *D, const ParsedAttr &AL) { 601406c3fb27SDimitry Andric D->addAttr(Attr::Create(S.Context, AL)); 601506c3fb27SDimitry Andric } 601606c3fb27SDimitry Andric 6017480093f4SDimitry Andric static void handleCFGuardAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 6018480093f4SDimitry Andric // The guard attribute takes a single identifier argument. 6019480093f4SDimitry Andric 6020480093f4SDimitry Andric if (!AL.isArgIdent(0)) { 6021480093f4SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 6022480093f4SDimitry Andric << AL << AANT_ArgumentIdentifier; 6023480093f4SDimitry Andric return; 6024480093f4SDimitry Andric } 6025480093f4SDimitry Andric 6026480093f4SDimitry Andric CFGuardAttr::GuardArg Arg; 6027480093f4SDimitry Andric IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; 6028480093f4SDimitry Andric if (!CFGuardAttr::ConvertStrToGuardArg(II->getName(), Arg)) { 6029480093f4SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; 6030480093f4SDimitry Andric return; 6031480093f4SDimitry Andric } 6032480093f4SDimitry Andric 6033480093f4SDimitry Andric D->addAttr(::new (S.Context) CFGuardAttr(S.Context, AL, Arg)); 6034480093f4SDimitry Andric } 6035480093f4SDimitry Andric 6036e8d8bef9SDimitry Andric 6037e8d8bef9SDimitry Andric template <typename AttrTy> 6038e8d8bef9SDimitry Andric static const AttrTy *findEnforceTCBAttrByName(Decl *D, StringRef Name) { 6039e8d8bef9SDimitry Andric auto Attrs = D->specific_attrs<AttrTy>(); 6040e8d8bef9SDimitry Andric auto I = llvm::find_if(Attrs, 6041e8d8bef9SDimitry Andric [Name](const AttrTy *A) { 6042e8d8bef9SDimitry Andric return A->getTCBName() == Name; 6043e8d8bef9SDimitry Andric }); 6044e8d8bef9SDimitry Andric return I == Attrs.end() ? nullptr : *I; 6045e8d8bef9SDimitry Andric } 6046e8d8bef9SDimitry Andric 6047e8d8bef9SDimitry Andric template <typename AttrTy, typename ConflictingAttrTy> 6048e8d8bef9SDimitry Andric static void handleEnforceTCBAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 6049e8d8bef9SDimitry Andric StringRef Argument; 6050e8d8bef9SDimitry Andric if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) 6051e8d8bef9SDimitry Andric return; 6052e8d8bef9SDimitry Andric 6053e8d8bef9SDimitry Andric // A function cannot be have both regular and leaf membership in the same TCB. 6054e8d8bef9SDimitry Andric if (const ConflictingAttrTy *ConflictingAttr = 6055e8d8bef9SDimitry Andric findEnforceTCBAttrByName<ConflictingAttrTy>(D, Argument)) { 6056e8d8bef9SDimitry Andric // We could attach a note to the other attribute but in this case 6057e8d8bef9SDimitry Andric // there's no need given how the two are very close to each other. 6058e8d8bef9SDimitry Andric S.Diag(AL.getLoc(), diag::err_tcb_conflicting_attributes) 6059e8d8bef9SDimitry Andric << AL.getAttrName()->getName() << ConflictingAttr->getAttrName()->getName() 6060e8d8bef9SDimitry Andric << Argument; 6061e8d8bef9SDimitry Andric 6062e8d8bef9SDimitry Andric // Error recovery: drop the non-leaf attribute so that to suppress 6063e8d8bef9SDimitry Andric // all future warnings caused by erroneous attributes. The leaf attribute 6064e8d8bef9SDimitry Andric // needs to be kept because it can only suppresses warnings, not cause them. 6065e8d8bef9SDimitry Andric D->dropAttr<EnforceTCBAttr>(); 6066e8d8bef9SDimitry Andric return; 6067e8d8bef9SDimitry Andric } 6068e8d8bef9SDimitry Andric 6069e8d8bef9SDimitry Andric D->addAttr(AttrTy::Create(S.Context, Argument, AL)); 6070e8d8bef9SDimitry Andric } 6071e8d8bef9SDimitry Andric 6072e8d8bef9SDimitry Andric template <typename AttrTy, typename ConflictingAttrTy> 6073e8d8bef9SDimitry Andric static AttrTy *mergeEnforceTCBAttrImpl(Sema &S, Decl *D, const AttrTy &AL) { 6074e8d8bef9SDimitry Andric // Check if the new redeclaration has different leaf-ness in the same TCB. 6075e8d8bef9SDimitry Andric StringRef TCBName = AL.getTCBName(); 6076e8d8bef9SDimitry Andric if (const ConflictingAttrTy *ConflictingAttr = 6077e8d8bef9SDimitry Andric findEnforceTCBAttrByName<ConflictingAttrTy>(D, TCBName)) { 6078e8d8bef9SDimitry Andric S.Diag(ConflictingAttr->getLoc(), diag::err_tcb_conflicting_attributes) 6079e8d8bef9SDimitry Andric << ConflictingAttr->getAttrName()->getName() 6080e8d8bef9SDimitry Andric << AL.getAttrName()->getName() << TCBName; 6081e8d8bef9SDimitry Andric 6082e8d8bef9SDimitry Andric // Add a note so that the user could easily find the conflicting attribute. 6083e8d8bef9SDimitry Andric S.Diag(AL.getLoc(), diag::note_conflicting_attribute); 6084e8d8bef9SDimitry Andric 6085e8d8bef9SDimitry Andric // More error recovery. 6086e8d8bef9SDimitry Andric D->dropAttr<EnforceTCBAttr>(); 6087e8d8bef9SDimitry Andric return nullptr; 6088e8d8bef9SDimitry Andric } 6089e8d8bef9SDimitry Andric 6090e8d8bef9SDimitry Andric ASTContext &Context = S.getASTContext(); 6091e8d8bef9SDimitry Andric return ::new(Context) AttrTy(Context, AL, AL.getTCBName()); 6092e8d8bef9SDimitry Andric } 6093e8d8bef9SDimitry Andric 6094e8d8bef9SDimitry Andric EnforceTCBAttr *Sema::mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL) { 6095e8d8bef9SDimitry Andric return mergeEnforceTCBAttrImpl<EnforceTCBAttr, EnforceTCBLeafAttr>( 6096e8d8bef9SDimitry Andric *this, D, AL); 6097e8d8bef9SDimitry Andric } 6098e8d8bef9SDimitry Andric 6099e8d8bef9SDimitry Andric EnforceTCBLeafAttr *Sema::mergeEnforceTCBLeafAttr( 6100e8d8bef9SDimitry Andric Decl *D, const EnforceTCBLeafAttr &AL) { 6101e8d8bef9SDimitry Andric return mergeEnforceTCBAttrImpl<EnforceTCBLeafAttr, EnforceTCBAttr>( 6102e8d8bef9SDimitry Andric *this, D, AL); 6103e8d8bef9SDimitry Andric } 6104e8d8bef9SDimitry Andric 61050fca6ea1SDimitry Andric static void handleVTablePointerAuthentication(Sema &S, Decl *D, 61060fca6ea1SDimitry Andric const ParsedAttr &AL) { 61070fca6ea1SDimitry Andric CXXRecordDecl *Decl = cast<CXXRecordDecl>(D); 61080fca6ea1SDimitry Andric const uint32_t NumArgs = AL.getNumArgs(); 61090fca6ea1SDimitry Andric if (NumArgs > 4) { 61100fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 4; 61110fca6ea1SDimitry Andric AL.setInvalid(); 61120fca6ea1SDimitry Andric } 61130fca6ea1SDimitry Andric 61140fca6ea1SDimitry Andric if (NumArgs == 0) { 61150fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL; 61160fca6ea1SDimitry Andric AL.setInvalid(); 61170fca6ea1SDimitry Andric return; 61180fca6ea1SDimitry Andric } 61190fca6ea1SDimitry Andric 61200fca6ea1SDimitry Andric if (D->getAttr<VTablePointerAuthenticationAttr>()) { 61210fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_duplicated_vtable_pointer_auth) << Decl; 61220fca6ea1SDimitry Andric AL.setInvalid(); 61230fca6ea1SDimitry Andric } 61240fca6ea1SDimitry Andric 61250fca6ea1SDimitry Andric auto KeyType = VTablePointerAuthenticationAttr::VPtrAuthKeyType::DefaultKey; 61260fca6ea1SDimitry Andric if (AL.isArgIdent(0)) { 61270fca6ea1SDimitry Andric IdentifierLoc *IL = AL.getArgAsIdent(0); 61280fca6ea1SDimitry Andric if (!VTablePointerAuthenticationAttr::ConvertStrToVPtrAuthKeyType( 61290fca6ea1SDimitry Andric IL->Ident->getName(), KeyType)) { 61300fca6ea1SDimitry Andric S.Diag(IL->Loc, diag::err_invalid_authentication_key) << IL->Ident; 61310fca6ea1SDimitry Andric AL.setInvalid(); 61320fca6ea1SDimitry Andric } 61330fca6ea1SDimitry Andric if (KeyType == VTablePointerAuthenticationAttr::DefaultKey && 61340fca6ea1SDimitry Andric !S.getLangOpts().PointerAuthCalls) { 61350fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_no_default_vtable_pointer_auth) << 0; 61360fca6ea1SDimitry Andric AL.setInvalid(); 61370fca6ea1SDimitry Andric } 61380fca6ea1SDimitry Andric } else { 61390fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 61400fca6ea1SDimitry Andric << AL << AANT_ArgumentIdentifier; 61410fca6ea1SDimitry Andric return; 61420fca6ea1SDimitry Andric } 61430fca6ea1SDimitry Andric 61440fca6ea1SDimitry Andric auto AddressDiversityMode = VTablePointerAuthenticationAttr:: 61450fca6ea1SDimitry Andric AddressDiscriminationMode::DefaultAddressDiscrimination; 61460fca6ea1SDimitry Andric if (AL.getNumArgs() > 1) { 61470fca6ea1SDimitry Andric if (AL.isArgIdent(1)) { 61480fca6ea1SDimitry Andric IdentifierLoc *IL = AL.getArgAsIdent(1); 61490fca6ea1SDimitry Andric if (!VTablePointerAuthenticationAttr:: 61500fca6ea1SDimitry Andric ConvertStrToAddressDiscriminationMode(IL->Ident->getName(), 61510fca6ea1SDimitry Andric AddressDiversityMode)) { 61520fca6ea1SDimitry Andric S.Diag(IL->Loc, diag::err_invalid_address_discrimination) << IL->Ident; 61530fca6ea1SDimitry Andric AL.setInvalid(); 61540fca6ea1SDimitry Andric } 61550fca6ea1SDimitry Andric if (AddressDiversityMode == 61560fca6ea1SDimitry Andric VTablePointerAuthenticationAttr::DefaultAddressDiscrimination && 61570fca6ea1SDimitry Andric !S.getLangOpts().PointerAuthCalls) { 61580fca6ea1SDimitry Andric S.Diag(IL->Loc, diag::err_no_default_vtable_pointer_auth) << 1; 61590fca6ea1SDimitry Andric AL.setInvalid(); 61600fca6ea1SDimitry Andric } 61610fca6ea1SDimitry Andric } else { 61620fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 61630fca6ea1SDimitry Andric << AL << AANT_ArgumentIdentifier; 61640fca6ea1SDimitry Andric } 61650fca6ea1SDimitry Andric } 61660fca6ea1SDimitry Andric 61670fca6ea1SDimitry Andric auto ED = VTablePointerAuthenticationAttr::ExtraDiscrimination:: 61680fca6ea1SDimitry Andric DefaultExtraDiscrimination; 61690fca6ea1SDimitry Andric if (AL.getNumArgs() > 2) { 61700fca6ea1SDimitry Andric if (AL.isArgIdent(2)) { 61710fca6ea1SDimitry Andric IdentifierLoc *IL = AL.getArgAsIdent(2); 61720fca6ea1SDimitry Andric if (!VTablePointerAuthenticationAttr::ConvertStrToExtraDiscrimination( 61730fca6ea1SDimitry Andric IL->Ident->getName(), ED)) { 61740fca6ea1SDimitry Andric S.Diag(IL->Loc, diag::err_invalid_extra_discrimination) << IL->Ident; 61750fca6ea1SDimitry Andric AL.setInvalid(); 61760fca6ea1SDimitry Andric } 61770fca6ea1SDimitry Andric if (ED == VTablePointerAuthenticationAttr::DefaultExtraDiscrimination && 61780fca6ea1SDimitry Andric !S.getLangOpts().PointerAuthCalls) { 61790fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_no_default_vtable_pointer_auth) << 2; 61800fca6ea1SDimitry Andric AL.setInvalid(); 61810fca6ea1SDimitry Andric } 61820fca6ea1SDimitry Andric } else { 61830fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_argument_type) 61840fca6ea1SDimitry Andric << AL << AANT_ArgumentIdentifier; 61850fca6ea1SDimitry Andric } 61860fca6ea1SDimitry Andric } 61870fca6ea1SDimitry Andric 61880fca6ea1SDimitry Andric uint32_t CustomDiscriminationValue = 0; 61890fca6ea1SDimitry Andric if (ED == VTablePointerAuthenticationAttr::CustomDiscrimination) { 61900fca6ea1SDimitry Andric if (NumArgs < 4) { 61910fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_missing_custom_discrimination) << AL << 4; 61920fca6ea1SDimitry Andric AL.setInvalid(); 61930fca6ea1SDimitry Andric return; 61940fca6ea1SDimitry Andric } 61950fca6ea1SDimitry Andric if (NumArgs > 4) { 61960fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 4; 61970fca6ea1SDimitry Andric AL.setInvalid(); 61980fca6ea1SDimitry Andric } 61990fca6ea1SDimitry Andric 62000fca6ea1SDimitry Andric if (!AL.isArgExpr(3) || !S.checkUInt32Argument(AL, AL.getArgAsExpr(3), 62010fca6ea1SDimitry Andric CustomDiscriminationValue)) { 62020fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_invalid_custom_discrimination); 62030fca6ea1SDimitry Andric AL.setInvalid(); 62040fca6ea1SDimitry Andric } 62050fca6ea1SDimitry Andric } else if (NumArgs > 3) { 62060fca6ea1SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 3; 62070fca6ea1SDimitry Andric AL.setInvalid(); 62080fca6ea1SDimitry Andric } 62090fca6ea1SDimitry Andric 62100fca6ea1SDimitry Andric Decl->addAttr(::new (S.Context) VTablePointerAuthenticationAttr( 62110fca6ea1SDimitry Andric S.Context, AL, KeyType, AddressDiversityMode, ED, 62120fca6ea1SDimitry Andric CustomDiscriminationValue)); 62130fca6ea1SDimitry Andric } 62140fca6ea1SDimitry Andric 62150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 62160b57cec5SDimitry Andric // Top Level Sema Entry Points 62170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 62180b57cec5SDimitry Andric 621981ad6265SDimitry Andric // Returns true if the attribute must delay setting its arguments until after 622081ad6265SDimitry Andric // template instantiation, and false otherwise. 622181ad6265SDimitry Andric static bool MustDelayAttributeArguments(const ParsedAttr &AL) { 622281ad6265SDimitry Andric // Only attributes that accept expression parameter packs can delay arguments. 622381ad6265SDimitry Andric if (!AL.acceptsExprPack()) 622481ad6265SDimitry Andric return false; 622581ad6265SDimitry Andric 622681ad6265SDimitry Andric bool AttrHasVariadicArg = AL.hasVariadicArg(); 622781ad6265SDimitry Andric unsigned AttrNumArgs = AL.getNumArgMembers(); 622881ad6265SDimitry Andric for (size_t I = 0; I < std::min(AL.getNumArgs(), AttrNumArgs); ++I) { 622981ad6265SDimitry Andric bool IsLastAttrArg = I == (AttrNumArgs - 1); 623081ad6265SDimitry Andric // If the argument is the last argument and it is variadic it can contain 623181ad6265SDimitry Andric // any expression. 623281ad6265SDimitry Andric if (IsLastAttrArg && AttrHasVariadicArg) 623381ad6265SDimitry Andric return false; 623481ad6265SDimitry Andric Expr *E = AL.getArgAsExpr(I); 623581ad6265SDimitry Andric bool ArgMemberCanHoldExpr = AL.isParamExpr(I); 623681ad6265SDimitry Andric // If the expression is a pack expansion then arguments must be delayed 623781ad6265SDimitry Andric // unless the argument is an expression and it is the last argument of the 623881ad6265SDimitry Andric // attribute. 623981ad6265SDimitry Andric if (isa<PackExpansionExpr>(E)) 624081ad6265SDimitry Andric return !(IsLastAttrArg && ArgMemberCanHoldExpr); 624181ad6265SDimitry Andric // Last case is if the expression is value dependent then it must delay 624281ad6265SDimitry Andric // arguments unless the corresponding argument is able to hold the 624381ad6265SDimitry Andric // expression. 624481ad6265SDimitry Andric if (E->isValueDependent() && !ArgMemberCanHoldExpr) 624581ad6265SDimitry Andric return true; 624681ad6265SDimitry Andric } 624781ad6265SDimitry Andric return false; 624881ad6265SDimitry Andric } 624981ad6265SDimitry Andric 62500b57cec5SDimitry Andric /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if 62510b57cec5SDimitry Andric /// the attribute applies to decls. If the attribute is a type attribute, just 62520b57cec5SDimitry Andric /// silently ignore it if a GNU attribute. 625381ad6265SDimitry Andric static void 625481ad6265SDimitry Andric ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, 625581ad6265SDimitry Andric const Sema::ProcessDeclAttributeOptions &Options) { 62560b57cec5SDimitry Andric if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute) 62570b57cec5SDimitry Andric return; 62580b57cec5SDimitry Andric 62590b57cec5SDimitry Andric // Ignore C++11 attributes on declarator chunks: they appertain to the type 62600fca6ea1SDimitry Andric // instead. Note, isCXX11Attribute() will look at whether the attribute is 62610fca6ea1SDimitry Andric // [[]] or alignas, while isC23Attribute() will only look at [[]]. This is 62620fca6ea1SDimitry Andric // important for ensuring that alignas in C23 is properly handled on a 62630fca6ea1SDimitry Andric // structure member declaration because it is a type-specifier-qualifier in 62640fca6ea1SDimitry Andric // C but still applies to the declaration rather than the type. 62650fca6ea1SDimitry Andric if ((S.getLangOpts().CPlusPlus ? AL.isCXX11Attribute() 62660fca6ea1SDimitry Andric : AL.isC23Attribute()) && 62670fca6ea1SDimitry Andric !Options.IncludeCXX11Attributes) 62680b57cec5SDimitry Andric return; 62690b57cec5SDimitry Andric 62700b57cec5SDimitry Andric // Unknown attributes are automatically warned on. Target-specific attributes 62710b57cec5SDimitry Andric // which do not apply to the current target architecture are treated as 62720b57cec5SDimitry Andric // though they were unknown attributes. 62730b57cec5SDimitry Andric if (AL.getKind() == ParsedAttr::UnknownAttribute || 62740b57cec5SDimitry Andric !AL.existsInTarget(S.Context.getTargetInfo())) { 62750b57cec5SDimitry Andric S.Diag(AL.getLoc(), 627606c3fb27SDimitry Andric AL.isRegularKeywordAttribute() 627706c3fb27SDimitry Andric ? (unsigned)diag::err_keyword_not_supported_on_target 627806c3fb27SDimitry Andric : AL.isDeclspecAttribute() 62790b57cec5SDimitry Andric ? (unsigned)diag::warn_unhandled_ms_attribute_ignored 62800b57cec5SDimitry Andric : (unsigned)diag::warn_unknown_attribute_ignored) 6281e8d8bef9SDimitry Andric << AL << AL.getRange(); 62820b57cec5SDimitry Andric return; 62830b57cec5SDimitry Andric } 62840b57cec5SDimitry Andric 628581ad6265SDimitry Andric // Check if argument population must delayed to after template instantiation. 628681ad6265SDimitry Andric bool MustDelayArgs = MustDelayAttributeArguments(AL); 628781ad6265SDimitry Andric 628881ad6265SDimitry Andric // Argument number check must be skipped if arguments are delayed. 628981ad6265SDimitry Andric if (S.checkCommonAttributeFeatures(D, AL, MustDelayArgs)) 62900b57cec5SDimitry Andric return; 62910b57cec5SDimitry Andric 629281ad6265SDimitry Andric if (MustDelayArgs) { 629381ad6265SDimitry Andric AL.handleAttrWithDelayedArgs(S, D); 629481ad6265SDimitry Andric return; 629581ad6265SDimitry Andric } 629681ad6265SDimitry Andric 62970b57cec5SDimitry Andric switch (AL.getKind()) { 62980b57cec5SDimitry Andric default: 62995ffd83dbSDimitry Andric if (AL.getInfo().handleDeclAttribute(S, D, AL) != ParsedAttrInfo::NotHandled) 63005ffd83dbSDimitry Andric break; 63010b57cec5SDimitry Andric if (!AL.isStmtAttr()) { 63020b57cec5SDimitry Andric assert(AL.isTypeAttr() && "Non-type attribute not handled"); 630381ad6265SDimitry Andric } 630481ad6265SDimitry Andric if (AL.isTypeAttr()) { 630581ad6265SDimitry Andric if (Options.IgnoreTypeAttributes) 63060b57cec5SDimitry Andric break; 630706c3fb27SDimitry Andric if (!AL.isStandardAttributeSyntax() && !AL.isRegularKeywordAttribute()) { 630881ad6265SDimitry Andric // Non-[[]] type attributes are handled in processTypeAttrs(); silently 630981ad6265SDimitry Andric // move on. 631081ad6265SDimitry Andric break; 631181ad6265SDimitry Andric } 631281ad6265SDimitry Andric 631381ad6265SDimitry Andric // According to the C and C++ standards, we should never see a 631481ad6265SDimitry Andric // [[]] type attribute on a declaration. However, we have in the past 631581ad6265SDimitry Andric // allowed some type attributes to "slide" to the `DeclSpec`, so we need 631681ad6265SDimitry Andric // to continue to support this legacy behavior. We only do this, however, 631781ad6265SDimitry Andric // if 631881ad6265SDimitry Andric // - we actually have a `DeclSpec`, i.e. if we're looking at a 631981ad6265SDimitry Andric // `DeclaratorDecl`, or 632081ad6265SDimitry Andric // - we are looking at an alias-declaration, where historically we have 632181ad6265SDimitry Andric // allowed type attributes after the identifier to slide to the type. 632281ad6265SDimitry Andric if (AL.slidesFromDeclToDeclSpecLegacyBehavior() && 632381ad6265SDimitry Andric isa<DeclaratorDecl, TypeAliasDecl>(D)) { 632481ad6265SDimitry Andric // Suggest moving the attribute to the type instead, but only for our 632581ad6265SDimitry Andric // own vendor attributes; moving other vendors' attributes might hurt 632681ad6265SDimitry Andric // portability. 632781ad6265SDimitry Andric if (AL.isClangScope()) { 632881ad6265SDimitry Andric S.Diag(AL.getLoc(), diag::warn_type_attribute_deprecated_on_decl) 632981ad6265SDimitry Andric << AL << D->getLocation(); 633081ad6265SDimitry Andric } 633181ad6265SDimitry Andric 633281ad6265SDimitry Andric // Allow this type attribute to be handled in processTypeAttrs(); 633381ad6265SDimitry Andric // silently move on. 633481ad6265SDimitry Andric break; 633581ad6265SDimitry Andric } 633681ad6265SDimitry Andric 633781ad6265SDimitry Andric if (AL.getKind() == ParsedAttr::AT_Regparm) { 633881ad6265SDimitry Andric // `regparm` is a special case: It's a type attribute but we still want 633981ad6265SDimitry Andric // to treat it as if it had been written on the declaration because that 634081ad6265SDimitry Andric // way we'll be able to handle it directly in `processTypeAttr()`. 634181ad6265SDimitry Andric // If we treated `regparm` it as if it had been written on the 634281ad6265SDimitry Andric // `DeclSpec`, the logic in `distributeFunctionTypeAttrFromDeclSepc()` 634381ad6265SDimitry Andric // would try to move it to the declarator, but that doesn't work: We 634481ad6265SDimitry Andric // can't remove the attribute from the list of declaration attributes 634581ad6265SDimitry Andric // because it might be needed by other declarators in the same 634681ad6265SDimitry Andric // declaration. 634781ad6265SDimitry Andric break; 634881ad6265SDimitry Andric } 634981ad6265SDimitry Andric 635081ad6265SDimitry Andric if (AL.getKind() == ParsedAttr::AT_VectorSize) { 635181ad6265SDimitry Andric // `vector_size` is a special case: It's a type attribute semantically, 635281ad6265SDimitry Andric // but GCC expects the [[]] syntax to be written on the declaration (and 635381ad6265SDimitry Andric // warns that the attribute has no effect if it is placed on the 635481ad6265SDimitry Andric // decl-specifier-seq). 635581ad6265SDimitry Andric // Silently move on and allow the attribute to be handled in 635681ad6265SDimitry Andric // processTypeAttr(). 635781ad6265SDimitry Andric break; 635881ad6265SDimitry Andric } 635981ad6265SDimitry Andric 636081ad6265SDimitry Andric if (AL.getKind() == ParsedAttr::AT_NoDeref) { 636181ad6265SDimitry Andric // FIXME: `noderef` currently doesn't work correctly in [[]] syntax. 636281ad6265SDimitry Andric // See https://github.com/llvm/llvm-project/issues/55790 for details. 636381ad6265SDimitry Andric // We allow processTypeAttrs() to emit a warning and silently move on. 636481ad6265SDimitry Andric break; 636581ad6265SDimitry Andric } 63660b57cec5SDimitry Andric } 6367fe6060f1SDimitry Andric // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a 6368fe6060f1SDimitry Andric // statement attribute is not written on a declaration, but this code is 636981ad6265SDimitry Andric // needed for type attributes as well as statement attributes in Attr.td 637081ad6265SDimitry Andric // that do not list any subjects. 637181ad6265SDimitry Andric S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl) 637206c3fb27SDimitry Andric << AL << AL.isRegularKeywordAttribute() << D->getLocation(); 63730b57cec5SDimitry Andric break; 63740b57cec5SDimitry Andric case ParsedAttr::AT_Interrupt: 63750b57cec5SDimitry Andric handleInterruptAttr(S, D, AL); 63760b57cec5SDimitry Andric break; 63770b57cec5SDimitry Andric case ParsedAttr::AT_X86ForceAlignArgPointer: 63780fca6ea1SDimitry Andric S.X86().handleForceAlignArgPointerAttr(D, AL); 63790b57cec5SDimitry Andric break; 6380bdd1243dSDimitry Andric case ParsedAttr::AT_ReadOnlyPlacement: 6381bdd1243dSDimitry Andric handleSimpleAttribute<ReadOnlyPlacementAttr>(S, D, AL); 6382bdd1243dSDimitry Andric break; 63830b57cec5SDimitry Andric case ParsedAttr::AT_DLLExport: 63840b57cec5SDimitry Andric case ParsedAttr::AT_DLLImport: 63850b57cec5SDimitry Andric handleDLLAttr(S, D, AL); 63860b57cec5SDimitry Andric break; 63870b57cec5SDimitry Andric case ParsedAttr::AT_AMDGPUFlatWorkGroupSize: 63880fca6ea1SDimitry Andric S.AMDGPU().handleAMDGPUFlatWorkGroupSizeAttr(D, AL); 63890b57cec5SDimitry Andric break; 63900b57cec5SDimitry Andric case ParsedAttr::AT_AMDGPUWavesPerEU: 63910fca6ea1SDimitry Andric S.AMDGPU().handleAMDGPUWavesPerEUAttr(D, AL); 63920b57cec5SDimitry Andric break; 63930b57cec5SDimitry Andric case ParsedAttr::AT_AMDGPUNumSGPR: 63940fca6ea1SDimitry Andric S.AMDGPU().handleAMDGPUNumSGPRAttr(D, AL); 63950b57cec5SDimitry Andric break; 63960b57cec5SDimitry Andric case ParsedAttr::AT_AMDGPUNumVGPR: 63970fca6ea1SDimitry Andric S.AMDGPU().handleAMDGPUNumVGPRAttr(D, AL); 63980fca6ea1SDimitry Andric break; 63990fca6ea1SDimitry Andric case ParsedAttr::AT_AMDGPUMaxNumWorkGroups: 64000fca6ea1SDimitry Andric S.AMDGPU().handleAMDGPUMaxNumWorkGroupsAttr(D, AL); 64010b57cec5SDimitry Andric break; 64020b57cec5SDimitry Andric case ParsedAttr::AT_AVRSignal: 64030fca6ea1SDimitry Andric S.AVR().handleSignalAttr(D, AL); 64040b57cec5SDimitry Andric break; 6405480093f4SDimitry Andric case ParsedAttr::AT_BPFPreserveAccessIndex: 64060fca6ea1SDimitry Andric S.BPF().handlePreserveAccessIndexAttr(D, AL); 6407480093f4SDimitry Andric break; 64085f757f3fSDimitry Andric case ParsedAttr::AT_BPFPreserveStaticOffset: 64095f757f3fSDimitry Andric handleSimpleAttribute<BPFPreserveStaticOffsetAttr>(S, D, AL); 64105f757f3fSDimitry Andric break; 6411349cc55cSDimitry Andric case ParsedAttr::AT_BTFDeclTag: 6412349cc55cSDimitry Andric handleBTFDeclTagAttr(S, D, AL); 6413349cc55cSDimitry Andric break; 6414480093f4SDimitry Andric case ParsedAttr::AT_WebAssemblyExportName: 64150fca6ea1SDimitry Andric S.Wasm().handleWebAssemblyExportNameAttr(D, AL); 6416480093f4SDimitry Andric break; 64170b57cec5SDimitry Andric case ParsedAttr::AT_WebAssemblyImportModule: 64180fca6ea1SDimitry Andric S.Wasm().handleWebAssemblyImportModuleAttr(D, AL); 64190b57cec5SDimitry Andric break; 64200b57cec5SDimitry Andric case ParsedAttr::AT_WebAssemblyImportName: 64210fca6ea1SDimitry Andric S.Wasm().handleWebAssemblyImportNameAttr(D, AL); 64220b57cec5SDimitry Andric break; 64230b57cec5SDimitry Andric case ParsedAttr::AT_IBOutlet: 64240fca6ea1SDimitry Andric S.ObjC().handleIBOutlet(D, AL); 64250b57cec5SDimitry Andric break; 64260b57cec5SDimitry Andric case ParsedAttr::AT_IBOutletCollection: 64270fca6ea1SDimitry Andric S.ObjC().handleIBOutletCollection(D, AL); 64280b57cec5SDimitry Andric break; 64290b57cec5SDimitry Andric case ParsedAttr::AT_IFunc: 64300b57cec5SDimitry Andric handleIFuncAttr(S, D, AL); 64310b57cec5SDimitry Andric break; 64320b57cec5SDimitry Andric case ParsedAttr::AT_Alias: 64330b57cec5SDimitry Andric handleAliasAttr(S, D, AL); 64340b57cec5SDimitry Andric break; 64350b57cec5SDimitry Andric case ParsedAttr::AT_Aligned: 64360b57cec5SDimitry Andric handleAlignedAttr(S, D, AL); 64370b57cec5SDimitry Andric break; 64380b57cec5SDimitry Andric case ParsedAttr::AT_AlignValue: 64390b57cec5SDimitry Andric handleAlignValueAttr(S, D, AL); 64400b57cec5SDimitry Andric break; 64410b57cec5SDimitry Andric case ParsedAttr::AT_AllocSize: 64420b57cec5SDimitry Andric handleAllocSizeAttr(S, D, AL); 64430b57cec5SDimitry Andric break; 64440b57cec5SDimitry Andric case ParsedAttr::AT_AlwaysInline: 64450b57cec5SDimitry Andric handleAlwaysInlineAttr(S, D, AL); 64460b57cec5SDimitry Andric break; 64470b57cec5SDimitry Andric case ParsedAttr::AT_AnalyzerNoReturn: 64480b57cec5SDimitry Andric handleAnalyzerNoReturnAttr(S, D, AL); 64490b57cec5SDimitry Andric break; 64500b57cec5SDimitry Andric case ParsedAttr::AT_TLSModel: 64510b57cec5SDimitry Andric handleTLSModelAttr(S, D, AL); 64520b57cec5SDimitry Andric break; 64530b57cec5SDimitry Andric case ParsedAttr::AT_Annotate: 64540b57cec5SDimitry Andric handleAnnotateAttr(S, D, AL); 64550b57cec5SDimitry Andric break; 64560b57cec5SDimitry Andric case ParsedAttr::AT_Availability: 64570b57cec5SDimitry Andric handleAvailabilityAttr(S, D, AL); 64580b57cec5SDimitry Andric break; 64590b57cec5SDimitry Andric case ParsedAttr::AT_CarriesDependency: 64600b57cec5SDimitry Andric handleDependencyAttr(S, scope, D, AL); 64610b57cec5SDimitry Andric break; 64620b57cec5SDimitry Andric case ParsedAttr::AT_CPUDispatch: 64630b57cec5SDimitry Andric case ParsedAttr::AT_CPUSpecific: 64640b57cec5SDimitry Andric handleCPUSpecificAttr(S, D, AL); 64650b57cec5SDimitry Andric break; 64660b57cec5SDimitry Andric case ParsedAttr::AT_Common: 64670b57cec5SDimitry Andric handleCommonAttr(S, D, AL); 64680b57cec5SDimitry Andric break; 64690b57cec5SDimitry Andric case ParsedAttr::AT_CUDAConstant: 64700b57cec5SDimitry Andric handleConstantAttr(S, D, AL); 64710b57cec5SDimitry Andric break; 64720b57cec5SDimitry Andric case ParsedAttr::AT_PassObjectSize: 64730b57cec5SDimitry Andric handlePassObjectSizeAttr(S, D, AL); 64740b57cec5SDimitry Andric break; 64750b57cec5SDimitry Andric case ParsedAttr::AT_Constructor: 64760b57cec5SDimitry Andric handleConstructorAttr(S, D, AL); 64770b57cec5SDimitry Andric break; 64780b57cec5SDimitry Andric case ParsedAttr::AT_Deprecated: 64790b57cec5SDimitry Andric handleDeprecatedAttr(S, D, AL); 64800b57cec5SDimitry Andric break; 64810b57cec5SDimitry Andric case ParsedAttr::AT_Destructor: 64820b57cec5SDimitry Andric handleDestructorAttr(S, D, AL); 64830b57cec5SDimitry Andric break; 64840b57cec5SDimitry Andric case ParsedAttr::AT_EnableIf: 64850b57cec5SDimitry Andric handleEnableIfAttr(S, D, AL); 64860b57cec5SDimitry Andric break; 6487349cc55cSDimitry Andric case ParsedAttr::AT_Error: 6488349cc55cSDimitry Andric handleErrorAttr(S, D, AL); 6489349cc55cSDimitry Andric break; 64900fca6ea1SDimitry Andric case ParsedAttr::AT_ExcludeFromExplicitInstantiation: 64910fca6ea1SDimitry Andric handleExcludeFromExplicitInstantiationAttr(S, D, AL); 64920fca6ea1SDimitry Andric break; 64930b57cec5SDimitry Andric case ParsedAttr::AT_DiagnoseIf: 64940b57cec5SDimitry Andric handleDiagnoseIfAttr(S, D, AL); 64950b57cec5SDimitry Andric break; 64960eae32dcSDimitry Andric case ParsedAttr::AT_DiagnoseAsBuiltin: 64970eae32dcSDimitry Andric handleDiagnoseAsBuiltinAttr(S, D, AL); 64980eae32dcSDimitry Andric break; 6499480093f4SDimitry Andric case ParsedAttr::AT_NoBuiltin: 6500480093f4SDimitry Andric handleNoBuiltinAttr(S, D, AL); 6501480093f4SDimitry Andric break; 65020b57cec5SDimitry Andric case ParsedAttr::AT_ExtVectorType: 65030b57cec5SDimitry Andric handleExtVectorTypeAttr(S, D, AL); 65040b57cec5SDimitry Andric break; 65050b57cec5SDimitry Andric case ParsedAttr::AT_ExternalSourceSymbol: 65060b57cec5SDimitry Andric handleExternalSourceSymbolAttr(S, D, AL); 65070b57cec5SDimitry Andric break; 65080b57cec5SDimitry Andric case ParsedAttr::AT_MinSize: 65090b57cec5SDimitry Andric handleMinSizeAttr(S, D, AL); 65100b57cec5SDimitry Andric break; 65110b57cec5SDimitry Andric case ParsedAttr::AT_OptimizeNone: 65120b57cec5SDimitry Andric handleOptimizeNoneAttr(S, D, AL); 65130b57cec5SDimitry Andric break; 65140b57cec5SDimitry Andric case ParsedAttr::AT_EnumExtensibility: 65150b57cec5SDimitry Andric handleEnumExtensibilityAttr(S, D, AL); 65160b57cec5SDimitry Andric break; 6517480093f4SDimitry Andric case ParsedAttr::AT_SYCLKernel: 65180fca6ea1SDimitry Andric S.SYCL().handleKernelAttr(D, AL); 6519480093f4SDimitry Andric break; 652004eeddc0SDimitry Andric case ParsedAttr::AT_SYCLSpecialClass: 652104eeddc0SDimitry Andric handleSimpleAttribute<SYCLSpecialClassAttr>(S, D, AL); 652204eeddc0SDimitry Andric break; 65230b57cec5SDimitry Andric case ParsedAttr::AT_Format: 65240b57cec5SDimitry Andric handleFormatAttr(S, D, AL); 65250b57cec5SDimitry Andric break; 65260b57cec5SDimitry Andric case ParsedAttr::AT_FormatArg: 65270b57cec5SDimitry Andric handleFormatArgAttr(S, D, AL); 65280b57cec5SDimitry Andric break; 65290b57cec5SDimitry Andric case ParsedAttr::AT_Callback: 65300b57cec5SDimitry Andric handleCallbackAttr(S, D, AL); 65310b57cec5SDimitry Andric break; 6532e8d8bef9SDimitry Andric case ParsedAttr::AT_CalledOnce: 6533e8d8bef9SDimitry Andric handleCalledOnceAttr(S, D, AL); 6534e8d8bef9SDimitry Andric break; 653506c3fb27SDimitry Andric case ParsedAttr::AT_NVPTXKernel: 65360b57cec5SDimitry Andric case ParsedAttr::AT_CUDAGlobal: 65370b57cec5SDimitry Andric handleGlobalAttr(S, D, AL); 65380b57cec5SDimitry Andric break; 65390b57cec5SDimitry Andric case ParsedAttr::AT_CUDADevice: 6540e8d8bef9SDimitry Andric handleDeviceAttr(S, D, AL); 65410b57cec5SDimitry Andric break; 6542e8d8bef9SDimitry Andric case ParsedAttr::AT_HIPManaged: 6543e8d8bef9SDimitry Andric handleManagedAttr(S, D, AL); 6544e8d8bef9SDimitry Andric break; 65450b57cec5SDimitry Andric case ParsedAttr::AT_GNUInline: 65460b57cec5SDimitry Andric handleGNUInlineAttr(S, D, AL); 65470b57cec5SDimitry Andric break; 65480b57cec5SDimitry Andric case ParsedAttr::AT_CUDALaunchBounds: 65490b57cec5SDimitry Andric handleLaunchBoundsAttr(S, D, AL); 65500b57cec5SDimitry Andric break; 65510b57cec5SDimitry Andric case ParsedAttr::AT_Restrict: 65520b57cec5SDimitry Andric handleRestrictAttr(S, D, AL); 65530b57cec5SDimitry Andric break; 65540b57cec5SDimitry Andric case ParsedAttr::AT_Mode: 65550b57cec5SDimitry Andric handleModeAttr(S, D, AL); 65560b57cec5SDimitry Andric break; 65570b57cec5SDimitry Andric case ParsedAttr::AT_NonNull: 65580b57cec5SDimitry Andric if (auto *PVD = dyn_cast<ParmVarDecl>(D)) 65590b57cec5SDimitry Andric handleNonNullAttrParameter(S, PVD, AL); 65600b57cec5SDimitry Andric else 65610b57cec5SDimitry Andric handleNonNullAttr(S, D, AL); 65620b57cec5SDimitry Andric break; 65630b57cec5SDimitry Andric case ParsedAttr::AT_ReturnsNonNull: 65640b57cec5SDimitry Andric handleReturnsNonNullAttr(S, D, AL); 65650b57cec5SDimitry Andric break; 65660b57cec5SDimitry Andric case ParsedAttr::AT_NoEscape: 65670b57cec5SDimitry Andric handleNoEscapeAttr(S, D, AL); 65680b57cec5SDimitry Andric break; 6569bdd1243dSDimitry Andric case ParsedAttr::AT_MaybeUndef: 6570bdd1243dSDimitry Andric handleSimpleAttribute<MaybeUndefAttr>(S, D, AL); 6571bdd1243dSDimitry Andric break; 65720b57cec5SDimitry Andric case ParsedAttr::AT_AssumeAligned: 65730b57cec5SDimitry Andric handleAssumeAlignedAttr(S, D, AL); 65740b57cec5SDimitry Andric break; 65750b57cec5SDimitry Andric case ParsedAttr::AT_AllocAlign: 65760b57cec5SDimitry Andric handleAllocAlignAttr(S, D, AL); 65770b57cec5SDimitry Andric break; 65780b57cec5SDimitry Andric case ParsedAttr::AT_Ownership: 65790b57cec5SDimitry Andric handleOwnershipAttr(S, D, AL); 65800b57cec5SDimitry Andric break; 65810b57cec5SDimitry Andric case ParsedAttr::AT_Naked: 65820b57cec5SDimitry Andric handleNakedAttr(S, D, AL); 65830b57cec5SDimitry Andric break; 65840b57cec5SDimitry Andric case ParsedAttr::AT_NoReturn: 65850b57cec5SDimitry Andric handleNoReturnAttr(S, D, AL); 65860b57cec5SDimitry Andric break; 658781ad6265SDimitry Andric case ParsedAttr::AT_CXX11NoReturn: 658881ad6265SDimitry Andric handleStandardNoReturnAttr(S, D, AL); 658981ad6265SDimitry Andric break; 65900b57cec5SDimitry Andric case ParsedAttr::AT_AnyX86NoCfCheck: 65910b57cec5SDimitry Andric handleNoCfCheckAttr(S, D, AL); 65920b57cec5SDimitry Andric break; 65930b57cec5SDimitry Andric case ParsedAttr::AT_NoThrow: 65940b57cec5SDimitry Andric if (!AL.isUsedAsTypeAttr()) 65950b57cec5SDimitry Andric handleSimpleAttribute<NoThrowAttr>(S, D, AL); 65960b57cec5SDimitry Andric break; 65970b57cec5SDimitry Andric case ParsedAttr::AT_CUDAShared: 65980b57cec5SDimitry Andric handleSharedAttr(S, D, AL); 65990b57cec5SDimitry Andric break; 66000b57cec5SDimitry Andric case ParsedAttr::AT_VecReturn: 66010b57cec5SDimitry Andric handleVecReturnAttr(S, D, AL); 66020b57cec5SDimitry Andric break; 66030b57cec5SDimitry Andric case ParsedAttr::AT_ObjCOwnership: 66040fca6ea1SDimitry Andric S.ObjC().handleOwnershipAttr(D, AL); 66050b57cec5SDimitry Andric break; 66060b57cec5SDimitry Andric case ParsedAttr::AT_ObjCPreciseLifetime: 66070fca6ea1SDimitry Andric S.ObjC().handlePreciseLifetimeAttr(D, AL); 66080b57cec5SDimitry Andric break; 66090b57cec5SDimitry Andric case ParsedAttr::AT_ObjCReturnsInnerPointer: 66100fca6ea1SDimitry Andric S.ObjC().handleReturnsInnerPointerAttr(D, AL); 66110b57cec5SDimitry Andric break; 66120b57cec5SDimitry Andric case ParsedAttr::AT_ObjCRequiresSuper: 66130fca6ea1SDimitry Andric S.ObjC().handleRequiresSuperAttr(D, AL); 66140b57cec5SDimitry Andric break; 66150b57cec5SDimitry Andric case ParsedAttr::AT_ObjCBridge: 66160fca6ea1SDimitry Andric S.ObjC().handleBridgeAttr(D, AL); 66170b57cec5SDimitry Andric break; 66180b57cec5SDimitry Andric case ParsedAttr::AT_ObjCBridgeMutable: 66190fca6ea1SDimitry Andric S.ObjC().handleBridgeMutableAttr(D, AL); 66200b57cec5SDimitry Andric break; 66210b57cec5SDimitry Andric case ParsedAttr::AT_ObjCBridgeRelated: 66220fca6ea1SDimitry Andric S.ObjC().handleBridgeRelatedAttr(D, AL); 66230b57cec5SDimitry Andric break; 66240b57cec5SDimitry Andric case ParsedAttr::AT_ObjCDesignatedInitializer: 66250fca6ea1SDimitry Andric S.ObjC().handleDesignatedInitializer(D, AL); 66260b57cec5SDimitry Andric break; 66270b57cec5SDimitry Andric case ParsedAttr::AT_ObjCRuntimeName: 66280fca6ea1SDimitry Andric S.ObjC().handleRuntimeName(D, AL); 66290b57cec5SDimitry Andric break; 66300b57cec5SDimitry Andric case ParsedAttr::AT_ObjCBoxable: 66310fca6ea1SDimitry Andric S.ObjC().handleBoxable(D, AL); 66320b57cec5SDimitry Andric break; 6633e8d8bef9SDimitry Andric case ParsedAttr::AT_NSErrorDomain: 66340fca6ea1SDimitry Andric S.ObjC().handleNSErrorDomain(D, AL); 6635e8d8bef9SDimitry Andric break; 66360b57cec5SDimitry Andric case ParsedAttr::AT_CFConsumed: 66370b57cec5SDimitry Andric case ParsedAttr::AT_NSConsumed: 66380b57cec5SDimitry Andric case ParsedAttr::AT_OSConsumed: 66390fca6ea1SDimitry Andric S.ObjC().AddXConsumedAttr(D, AL, 66400fca6ea1SDimitry Andric S.ObjC().parsedAttrToRetainOwnershipKind(AL), 66410b57cec5SDimitry Andric /*IsTemplateInstantiation=*/false); 66420b57cec5SDimitry Andric break; 66430b57cec5SDimitry Andric case ParsedAttr::AT_OSReturnsRetainedOnZero: 66440b57cec5SDimitry Andric handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnZeroAttr>( 66450fca6ea1SDimitry Andric S, D, AL, S.ObjC().isValidOSObjectOutParameter(D), 66460b57cec5SDimitry Andric diag::warn_ns_attribute_wrong_parameter_type, 66470b57cec5SDimitry Andric /*Extra Args=*/AL, /*pointer-to-OSObject-pointer*/ 3, AL.getRange()); 66480b57cec5SDimitry Andric break; 66490b57cec5SDimitry Andric case ParsedAttr::AT_OSReturnsRetainedOnNonZero: 66500b57cec5SDimitry Andric handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnNonZeroAttr>( 66510fca6ea1SDimitry Andric S, D, AL, S.ObjC().isValidOSObjectOutParameter(D), 66520b57cec5SDimitry Andric diag::warn_ns_attribute_wrong_parameter_type, 66530b57cec5SDimitry Andric /*Extra Args=*/AL, /*pointer-to-OSObject-poointer*/ 3, AL.getRange()); 66540b57cec5SDimitry Andric break; 66550b57cec5SDimitry Andric case ParsedAttr::AT_NSReturnsAutoreleased: 66560b57cec5SDimitry Andric case ParsedAttr::AT_NSReturnsNotRetained: 66570b57cec5SDimitry Andric case ParsedAttr::AT_NSReturnsRetained: 66580b57cec5SDimitry Andric case ParsedAttr::AT_CFReturnsNotRetained: 66590b57cec5SDimitry Andric case ParsedAttr::AT_CFReturnsRetained: 66600b57cec5SDimitry Andric case ParsedAttr::AT_OSReturnsNotRetained: 66610b57cec5SDimitry Andric case ParsedAttr::AT_OSReturnsRetained: 66620fca6ea1SDimitry Andric S.ObjC().handleXReturnsXRetainedAttr(D, AL); 66630b57cec5SDimitry Andric break; 66640b57cec5SDimitry Andric case ParsedAttr::AT_WorkGroupSizeHint: 66650b57cec5SDimitry Andric handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL); 66660b57cec5SDimitry Andric break; 66670b57cec5SDimitry Andric case ParsedAttr::AT_ReqdWorkGroupSize: 66680b57cec5SDimitry Andric handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL); 66690b57cec5SDimitry Andric break; 66700b57cec5SDimitry Andric case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize: 66710fca6ea1SDimitry Andric S.OpenCL().handleSubGroupSize(D, AL); 66720b57cec5SDimitry Andric break; 66730b57cec5SDimitry Andric case ParsedAttr::AT_VecTypeHint: 66740b57cec5SDimitry Andric handleVecTypeHint(S, D, AL); 66750b57cec5SDimitry Andric break; 66760b57cec5SDimitry Andric case ParsedAttr::AT_InitPriority: 66770b57cec5SDimitry Andric handleInitPriorityAttr(S, D, AL); 66780b57cec5SDimitry Andric break; 66790b57cec5SDimitry Andric case ParsedAttr::AT_Packed: 66800b57cec5SDimitry Andric handlePackedAttr(S, D, AL); 66810b57cec5SDimitry Andric break; 6682e8d8bef9SDimitry Andric case ParsedAttr::AT_PreferredName: 6683e8d8bef9SDimitry Andric handlePreferredName(S, D, AL); 6684e8d8bef9SDimitry Andric break; 66850b57cec5SDimitry Andric case ParsedAttr::AT_Section: 66860b57cec5SDimitry Andric handleSectionAttr(S, D, AL); 66870b57cec5SDimitry Andric break; 66881db9f3b2SDimitry Andric case ParsedAttr::AT_CodeModel: 66891db9f3b2SDimitry Andric handleCodeModelAttr(S, D, AL); 66901db9f3b2SDimitry Andric break; 669181ad6265SDimitry Andric case ParsedAttr::AT_RandomizeLayout: 669281ad6265SDimitry Andric handleRandomizeLayoutAttr(S, D, AL); 669381ad6265SDimitry Andric break; 669481ad6265SDimitry Andric case ParsedAttr::AT_NoRandomizeLayout: 669581ad6265SDimitry Andric handleNoRandomizeLayoutAttr(S, D, AL); 669681ad6265SDimitry Andric break; 66970b57cec5SDimitry Andric case ParsedAttr::AT_CodeSeg: 66980b57cec5SDimitry Andric handleCodeSegAttr(S, D, AL); 66990b57cec5SDimitry Andric break; 67000b57cec5SDimitry Andric case ParsedAttr::AT_Target: 67010b57cec5SDimitry Andric handleTargetAttr(S, D, AL); 67020b57cec5SDimitry Andric break; 6703bdd1243dSDimitry Andric case ParsedAttr::AT_TargetVersion: 6704bdd1243dSDimitry Andric handleTargetVersionAttr(S, D, AL); 6705bdd1243dSDimitry Andric break; 67064824e7fdSDimitry Andric case ParsedAttr::AT_TargetClones: 67074824e7fdSDimitry Andric handleTargetClonesAttr(S, D, AL); 67084824e7fdSDimitry Andric break; 67090b57cec5SDimitry Andric case ParsedAttr::AT_MinVectorWidth: 67100b57cec5SDimitry Andric handleMinVectorWidthAttr(S, D, AL); 67110b57cec5SDimitry Andric break; 67120b57cec5SDimitry Andric case ParsedAttr::AT_Unavailable: 67130b57cec5SDimitry Andric handleAttrWithMessage<UnavailableAttr>(S, D, AL); 67140b57cec5SDimitry Andric break; 67150fca6ea1SDimitry Andric case ParsedAttr::AT_OMPAssume: 67160fca6ea1SDimitry Andric S.OpenMP().handleOMPAssumeAttr(D, AL); 6717e8d8bef9SDimitry Andric break; 6718480093f4SDimitry Andric case ParsedAttr::AT_ObjCDirect: 67190fca6ea1SDimitry Andric S.ObjC().handleDirectAttr(D, AL); 6720480093f4SDimitry Andric break; 6721480093f4SDimitry Andric case ParsedAttr::AT_ObjCDirectMembers: 67220fca6ea1SDimitry Andric S.ObjC().handleDirectMembersAttr(D, AL); 6723480093f4SDimitry Andric handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); 6724480093f4SDimitry Andric break; 67250b57cec5SDimitry Andric case ParsedAttr::AT_ObjCExplicitProtocolImpl: 67260fca6ea1SDimitry Andric S.ObjC().handleSuppresProtocolAttr(D, AL); 67270b57cec5SDimitry Andric break; 67280b57cec5SDimitry Andric case ParsedAttr::AT_Unused: 67290b57cec5SDimitry Andric handleUnusedAttr(S, D, AL); 67300b57cec5SDimitry Andric break; 67310b57cec5SDimitry Andric case ParsedAttr::AT_Visibility: 67320b57cec5SDimitry Andric handleVisibilityAttr(S, D, AL, false); 67330b57cec5SDimitry Andric break; 67340b57cec5SDimitry Andric case ParsedAttr::AT_TypeVisibility: 67350b57cec5SDimitry Andric handleVisibilityAttr(S, D, AL, true); 67360b57cec5SDimitry Andric break; 67370b57cec5SDimitry Andric case ParsedAttr::AT_WarnUnusedResult: 67380b57cec5SDimitry Andric handleWarnUnusedResult(S, D, AL); 67390b57cec5SDimitry Andric break; 67400b57cec5SDimitry Andric case ParsedAttr::AT_WeakRef: 67410b57cec5SDimitry Andric handleWeakRefAttr(S, D, AL); 67420b57cec5SDimitry Andric break; 67430b57cec5SDimitry Andric case ParsedAttr::AT_WeakImport: 67440b57cec5SDimitry Andric handleWeakImportAttr(S, D, AL); 67450b57cec5SDimitry Andric break; 67460b57cec5SDimitry Andric case ParsedAttr::AT_TransparentUnion: 67470b57cec5SDimitry Andric handleTransparentUnionAttr(S, D, AL); 67480b57cec5SDimitry Andric break; 67490b57cec5SDimitry Andric case ParsedAttr::AT_ObjCMethodFamily: 67500fca6ea1SDimitry Andric S.ObjC().handleMethodFamilyAttr(D, AL); 67510b57cec5SDimitry Andric break; 67520b57cec5SDimitry Andric case ParsedAttr::AT_ObjCNSObject: 67530fca6ea1SDimitry Andric S.ObjC().handleNSObject(D, AL); 67540b57cec5SDimitry Andric break; 67550b57cec5SDimitry Andric case ParsedAttr::AT_ObjCIndependentClass: 67560fca6ea1SDimitry Andric S.ObjC().handleIndependentClass(D, AL); 67570b57cec5SDimitry Andric break; 67580b57cec5SDimitry Andric case ParsedAttr::AT_Blocks: 67590fca6ea1SDimitry Andric S.ObjC().handleBlocksAttr(D, AL); 67600b57cec5SDimitry Andric break; 67610b57cec5SDimitry Andric case ParsedAttr::AT_Sentinel: 67620b57cec5SDimitry Andric handleSentinelAttr(S, D, AL); 67630b57cec5SDimitry Andric break; 67640b57cec5SDimitry Andric case ParsedAttr::AT_Cleanup: 67650b57cec5SDimitry Andric handleCleanupAttr(S, D, AL); 67660b57cec5SDimitry Andric break; 67670b57cec5SDimitry Andric case ParsedAttr::AT_NoDebug: 67680b57cec5SDimitry Andric handleNoDebugAttr(S, D, AL); 67690b57cec5SDimitry Andric break; 67705ffd83dbSDimitry Andric case ParsedAttr::AT_CmseNSEntry: 67710fca6ea1SDimitry Andric S.ARM().handleCmseNSEntryAttr(D, AL); 6772a7dea167SDimitry Andric break; 67730b57cec5SDimitry Andric case ParsedAttr::AT_StdCall: 67740b57cec5SDimitry Andric case ParsedAttr::AT_CDecl: 67750b57cec5SDimitry Andric case ParsedAttr::AT_FastCall: 67760b57cec5SDimitry Andric case ParsedAttr::AT_ThisCall: 67770b57cec5SDimitry Andric case ParsedAttr::AT_Pascal: 67780b57cec5SDimitry Andric case ParsedAttr::AT_RegCall: 67790b57cec5SDimitry Andric case ParsedAttr::AT_SwiftCall: 6780fe6060f1SDimitry Andric case ParsedAttr::AT_SwiftAsyncCall: 67810b57cec5SDimitry Andric case ParsedAttr::AT_VectorCall: 67820b57cec5SDimitry Andric case ParsedAttr::AT_MSABI: 67830b57cec5SDimitry Andric case ParsedAttr::AT_SysVABI: 67840b57cec5SDimitry Andric case ParsedAttr::AT_Pcs: 67850b57cec5SDimitry Andric case ParsedAttr::AT_IntelOclBicc: 67860b57cec5SDimitry Andric case ParsedAttr::AT_PreserveMost: 67870b57cec5SDimitry Andric case ParsedAttr::AT_PreserveAll: 67880b57cec5SDimitry Andric case ParsedAttr::AT_AArch64VectorPcs: 678981ad6265SDimitry Andric case ParsedAttr::AT_AArch64SVEPcs: 679081ad6265SDimitry Andric case ParsedAttr::AT_AMDGPUKernelCall: 67915f757f3fSDimitry Andric case ParsedAttr::AT_M68kRTD: 67920fca6ea1SDimitry Andric case ParsedAttr::AT_PreserveNone: 67930fca6ea1SDimitry Andric case ParsedAttr::AT_RISCVVectorCC: 67940b57cec5SDimitry Andric handleCallConvAttr(S, D, AL); 67950b57cec5SDimitry Andric break; 67960b57cec5SDimitry Andric case ParsedAttr::AT_Suppress: 67970b57cec5SDimitry Andric handleSuppressAttr(S, D, AL); 67980b57cec5SDimitry Andric break; 6799a7dea167SDimitry Andric case ParsedAttr::AT_Owner: 6800a7dea167SDimitry Andric case ParsedAttr::AT_Pointer: 6801a7dea167SDimitry Andric handleLifetimeCategoryAttr(S, D, AL); 6802a7dea167SDimitry Andric break; 68030b57cec5SDimitry Andric case ParsedAttr::AT_OpenCLAccess: 68040fca6ea1SDimitry Andric S.OpenCL().handleAccessAttr(D, AL); 68050b57cec5SDimitry Andric break; 68060b57cec5SDimitry Andric case ParsedAttr::AT_OpenCLNoSVM: 68070fca6ea1SDimitry Andric S.OpenCL().handleNoSVMAttr(D, AL); 68080b57cec5SDimitry Andric break; 68090b57cec5SDimitry Andric case ParsedAttr::AT_SwiftContext: 68100fca6ea1SDimitry Andric S.Swift().AddParameterABIAttr(D, AL, ParameterABI::SwiftContext); 68110b57cec5SDimitry Andric break; 6812fe6060f1SDimitry Andric case ParsedAttr::AT_SwiftAsyncContext: 68130fca6ea1SDimitry Andric S.Swift().AddParameterABIAttr(D, AL, ParameterABI::SwiftAsyncContext); 6814fe6060f1SDimitry Andric break; 68150b57cec5SDimitry Andric case ParsedAttr::AT_SwiftErrorResult: 68160fca6ea1SDimitry Andric S.Swift().AddParameterABIAttr(D, AL, ParameterABI::SwiftErrorResult); 68170b57cec5SDimitry Andric break; 68180b57cec5SDimitry Andric case ParsedAttr::AT_SwiftIndirectResult: 68190fca6ea1SDimitry Andric S.Swift().AddParameterABIAttr(D, AL, ParameterABI::SwiftIndirectResult); 68200b57cec5SDimitry Andric break; 68210b57cec5SDimitry Andric case ParsedAttr::AT_InternalLinkage: 68220b57cec5SDimitry Andric handleInternalLinkageAttr(S, D, AL); 68230b57cec5SDimitry Andric break; 682481ad6265SDimitry Andric case ParsedAttr::AT_ZeroCallUsedRegs: 682581ad6265SDimitry Andric handleZeroCallUsedRegsAttr(S, D, AL); 682681ad6265SDimitry Andric break; 6827753f127fSDimitry Andric case ParsedAttr::AT_FunctionReturnThunks: 6828753f127fSDimitry Andric handleFunctionReturnThunksAttr(S, D, AL); 6829753f127fSDimitry Andric break; 683006c3fb27SDimitry Andric case ParsedAttr::AT_NoMerge: 683106c3fb27SDimitry Andric handleNoMergeAttr(S, D, AL); 683206c3fb27SDimitry Andric break; 68335f757f3fSDimitry Andric case ParsedAttr::AT_NoUniqueAddress: 68345f757f3fSDimitry Andric handleNoUniqueAddressAttr(S, D, AL); 68355f757f3fSDimitry Andric break; 683606c3fb27SDimitry Andric 683706c3fb27SDimitry Andric case ParsedAttr::AT_AvailableOnlyInDefaultEvalMethod: 683806c3fb27SDimitry Andric handleAvailableOnlyInDefaultEvalMethod(S, D, AL); 683906c3fb27SDimitry Andric break; 68400b57cec5SDimitry Andric 6841297eecfbSDimitry Andric case ParsedAttr::AT_CountedBy: 68420fca6ea1SDimitry Andric case ParsedAttr::AT_CountedByOrNull: 68430fca6ea1SDimitry Andric case ParsedAttr::AT_SizedBy: 68440fca6ea1SDimitry Andric case ParsedAttr::AT_SizedByOrNull: 68450fca6ea1SDimitry Andric handleCountedByAttrField(S, D, AL); 6846297eecfbSDimitry Andric break; 6847297eecfbSDimitry Andric 68480b57cec5SDimitry Andric // Microsoft attributes: 68490b57cec5SDimitry Andric case ParsedAttr::AT_LayoutVersion: 68500b57cec5SDimitry Andric handleLayoutVersion(S, D, AL); 68510b57cec5SDimitry Andric break; 68520b57cec5SDimitry Andric case ParsedAttr::AT_Uuid: 68530b57cec5SDimitry Andric handleUuidAttr(S, D, AL); 68540b57cec5SDimitry Andric break; 68550b57cec5SDimitry Andric case ParsedAttr::AT_MSInheritance: 68560b57cec5SDimitry Andric handleMSInheritanceAttr(S, D, AL); 68570b57cec5SDimitry Andric break; 68580b57cec5SDimitry Andric case ParsedAttr::AT_Thread: 68590b57cec5SDimitry Andric handleDeclspecThreadAttr(S, D, AL); 68600b57cec5SDimitry Andric break; 68615f757f3fSDimitry Andric case ParsedAttr::AT_MSConstexpr: 68625f757f3fSDimitry Andric handleMSConstexprAttr(S, D, AL); 68635f757f3fSDimitry Andric break; 6864*52418fc2SDimitry Andric case ParsedAttr::AT_HybridPatchable: 6865*52418fc2SDimitry Andric handleSimpleAttribute<HybridPatchableAttr>(S, D, AL); 6866*52418fc2SDimitry Andric break; 68670b57cec5SDimitry Andric 686881ad6265SDimitry Andric // HLSL attributes: 686981ad6265SDimitry Andric case ParsedAttr::AT_HLSLNumThreads: 68700fca6ea1SDimitry Andric S.HLSL().handleNumThreadsAttr(D, AL); 687181ad6265SDimitry Andric break; 687281ad6265SDimitry Andric case ParsedAttr::AT_HLSLSV_GroupIndex: 68735f757f3fSDimitry Andric handleSimpleAttribute<HLSLSV_GroupIndexAttr>(S, D, AL); 687481ad6265SDimitry Andric break; 6875bdd1243dSDimitry Andric case ParsedAttr::AT_HLSLSV_DispatchThreadID: 68760fca6ea1SDimitry Andric S.HLSL().handleSV_DispatchThreadIDAttr(D, AL); 68770fca6ea1SDimitry Andric break; 68780fca6ea1SDimitry Andric case ParsedAttr::AT_HLSLPackOffset: 68790fca6ea1SDimitry Andric S.HLSL().handlePackOffsetAttr(D, AL); 6880bdd1243dSDimitry Andric break; 688181ad6265SDimitry Andric case ParsedAttr::AT_HLSLShader: 68820fca6ea1SDimitry Andric S.HLSL().handleShaderAttr(D, AL); 688381ad6265SDimitry Andric break; 6884bdd1243dSDimitry Andric case ParsedAttr::AT_HLSLResourceBinding: 68850fca6ea1SDimitry Andric S.HLSL().handleResourceBindingAttr(D, AL); 68860fca6ea1SDimitry Andric break; 68870fca6ea1SDimitry Andric case ParsedAttr::AT_HLSLResourceClass: 68880fca6ea1SDimitry Andric S.HLSL().handleResourceClassAttr(D, AL); 6889bdd1243dSDimitry Andric break; 68905f757f3fSDimitry Andric case ParsedAttr::AT_HLSLParamModifier: 68910fca6ea1SDimitry Andric S.HLSL().handleParamModifierAttr(D, AL); 68925f757f3fSDimitry Andric break; 689381ad6265SDimitry Andric 68940b57cec5SDimitry Andric case ParsedAttr::AT_AbiTag: 68950b57cec5SDimitry Andric handleAbiTagAttr(S, D, AL); 68960b57cec5SDimitry Andric break; 6897480093f4SDimitry Andric case ParsedAttr::AT_CFGuard: 6898480093f4SDimitry Andric handleCFGuardAttr(S, D, AL); 6899480093f4SDimitry Andric break; 69000b57cec5SDimitry Andric 69010b57cec5SDimitry Andric // Thread safety attributes: 69020b57cec5SDimitry Andric case ParsedAttr::AT_AssertExclusiveLock: 69030b57cec5SDimitry Andric handleAssertExclusiveLockAttr(S, D, AL); 69040b57cec5SDimitry Andric break; 69050b57cec5SDimitry Andric case ParsedAttr::AT_AssertSharedLock: 69060b57cec5SDimitry Andric handleAssertSharedLockAttr(S, D, AL); 69070b57cec5SDimitry Andric break; 69080b57cec5SDimitry Andric case ParsedAttr::AT_PtGuardedVar: 69090b57cec5SDimitry Andric handlePtGuardedVarAttr(S, D, AL); 69100b57cec5SDimitry Andric break; 69110b57cec5SDimitry Andric case ParsedAttr::AT_NoSanitize: 69120b57cec5SDimitry Andric handleNoSanitizeAttr(S, D, AL); 69130b57cec5SDimitry Andric break; 69140b57cec5SDimitry Andric case ParsedAttr::AT_NoSanitizeSpecific: 69150b57cec5SDimitry Andric handleNoSanitizeSpecificAttr(S, D, AL); 69160b57cec5SDimitry Andric break; 69170b57cec5SDimitry Andric case ParsedAttr::AT_GuardedBy: 69180b57cec5SDimitry Andric handleGuardedByAttr(S, D, AL); 69190b57cec5SDimitry Andric break; 69200b57cec5SDimitry Andric case ParsedAttr::AT_PtGuardedBy: 69210b57cec5SDimitry Andric handlePtGuardedByAttr(S, D, AL); 69220b57cec5SDimitry Andric break; 69230b57cec5SDimitry Andric case ParsedAttr::AT_ExclusiveTrylockFunction: 69240b57cec5SDimitry Andric handleExclusiveTrylockFunctionAttr(S, D, AL); 69250b57cec5SDimitry Andric break; 69260b57cec5SDimitry Andric case ParsedAttr::AT_LockReturned: 69270b57cec5SDimitry Andric handleLockReturnedAttr(S, D, AL); 69280b57cec5SDimitry Andric break; 69290b57cec5SDimitry Andric case ParsedAttr::AT_LocksExcluded: 69300b57cec5SDimitry Andric handleLocksExcludedAttr(S, D, AL); 69310b57cec5SDimitry Andric break; 69320b57cec5SDimitry Andric case ParsedAttr::AT_SharedTrylockFunction: 69330b57cec5SDimitry Andric handleSharedTrylockFunctionAttr(S, D, AL); 69340b57cec5SDimitry Andric break; 69350b57cec5SDimitry Andric case ParsedAttr::AT_AcquiredBefore: 69360b57cec5SDimitry Andric handleAcquiredBeforeAttr(S, D, AL); 69370b57cec5SDimitry Andric break; 69380b57cec5SDimitry Andric case ParsedAttr::AT_AcquiredAfter: 69390b57cec5SDimitry Andric handleAcquiredAfterAttr(S, D, AL); 69400b57cec5SDimitry Andric break; 69410b57cec5SDimitry Andric 69420b57cec5SDimitry Andric // Capability analysis attributes. 69430b57cec5SDimitry Andric case ParsedAttr::AT_Capability: 69440b57cec5SDimitry Andric case ParsedAttr::AT_Lockable: 69450b57cec5SDimitry Andric handleCapabilityAttr(S, D, AL); 69460b57cec5SDimitry Andric break; 69470b57cec5SDimitry Andric case ParsedAttr::AT_RequiresCapability: 69480b57cec5SDimitry Andric handleRequiresCapabilityAttr(S, D, AL); 69490b57cec5SDimitry Andric break; 69500b57cec5SDimitry Andric 69510b57cec5SDimitry Andric case ParsedAttr::AT_AssertCapability: 69520b57cec5SDimitry Andric handleAssertCapabilityAttr(S, D, AL); 69530b57cec5SDimitry Andric break; 69540b57cec5SDimitry Andric case ParsedAttr::AT_AcquireCapability: 69550b57cec5SDimitry Andric handleAcquireCapabilityAttr(S, D, AL); 69560b57cec5SDimitry Andric break; 69570b57cec5SDimitry Andric case ParsedAttr::AT_ReleaseCapability: 69580b57cec5SDimitry Andric handleReleaseCapabilityAttr(S, D, AL); 69590b57cec5SDimitry Andric break; 69600b57cec5SDimitry Andric case ParsedAttr::AT_TryAcquireCapability: 69610b57cec5SDimitry Andric handleTryAcquireCapabilityAttr(S, D, AL); 69620b57cec5SDimitry Andric break; 69630b57cec5SDimitry Andric 69640b57cec5SDimitry Andric // Consumed analysis attributes. 69650b57cec5SDimitry Andric case ParsedAttr::AT_Consumable: 69660b57cec5SDimitry Andric handleConsumableAttr(S, D, AL); 69670b57cec5SDimitry Andric break; 69680b57cec5SDimitry Andric case ParsedAttr::AT_CallableWhen: 69690b57cec5SDimitry Andric handleCallableWhenAttr(S, D, AL); 69700b57cec5SDimitry Andric break; 69710b57cec5SDimitry Andric case ParsedAttr::AT_ParamTypestate: 69720b57cec5SDimitry Andric handleParamTypestateAttr(S, D, AL); 69730b57cec5SDimitry Andric break; 69740b57cec5SDimitry Andric case ParsedAttr::AT_ReturnTypestate: 69750b57cec5SDimitry Andric handleReturnTypestateAttr(S, D, AL); 69760b57cec5SDimitry Andric break; 69770b57cec5SDimitry Andric case ParsedAttr::AT_SetTypestate: 69780b57cec5SDimitry Andric handleSetTypestateAttr(S, D, AL); 69790b57cec5SDimitry Andric break; 69800b57cec5SDimitry Andric case ParsedAttr::AT_TestTypestate: 69810b57cec5SDimitry Andric handleTestTypestateAttr(S, D, AL); 69820b57cec5SDimitry Andric break; 69830b57cec5SDimitry Andric 69840b57cec5SDimitry Andric // Type safety attributes. 69850b57cec5SDimitry Andric case ParsedAttr::AT_ArgumentWithTypeTag: 69860b57cec5SDimitry Andric handleArgumentWithTypeTagAttr(S, D, AL); 69870b57cec5SDimitry Andric break; 69880b57cec5SDimitry Andric case ParsedAttr::AT_TypeTagForDatatype: 69890b57cec5SDimitry Andric handleTypeTagForDatatypeAttr(S, D, AL); 69900b57cec5SDimitry Andric break; 69915ffd83dbSDimitry Andric 6992e8d8bef9SDimitry Andric // Swift attributes. 6993e8d8bef9SDimitry Andric case ParsedAttr::AT_SwiftAsyncName: 69940fca6ea1SDimitry Andric S.Swift().handleAsyncName(D, AL); 6995e8d8bef9SDimitry Andric break; 6996e8d8bef9SDimitry Andric case ParsedAttr::AT_SwiftAttr: 69970fca6ea1SDimitry Andric S.Swift().handleAttrAttr(D, AL); 6998e8d8bef9SDimitry Andric break; 6999e8d8bef9SDimitry Andric case ParsedAttr::AT_SwiftBridge: 70000fca6ea1SDimitry Andric S.Swift().handleBridge(D, AL); 7001e8d8bef9SDimitry Andric break; 7002e8d8bef9SDimitry Andric case ParsedAttr::AT_SwiftError: 70030fca6ea1SDimitry Andric S.Swift().handleError(D, AL); 7004e8d8bef9SDimitry Andric break; 7005e8d8bef9SDimitry Andric case ParsedAttr::AT_SwiftName: 70060fca6ea1SDimitry Andric S.Swift().handleName(D, AL); 7007e8d8bef9SDimitry Andric break; 7008e8d8bef9SDimitry Andric case ParsedAttr::AT_SwiftNewType: 70090fca6ea1SDimitry Andric S.Swift().handleNewType(D, AL); 7010e8d8bef9SDimitry Andric break; 7011e8d8bef9SDimitry Andric case ParsedAttr::AT_SwiftAsync: 70120fca6ea1SDimitry Andric S.Swift().handleAsyncAttr(D, AL); 7013e8d8bef9SDimitry Andric break; 7014fe6060f1SDimitry Andric case ParsedAttr::AT_SwiftAsyncError: 70150fca6ea1SDimitry Andric S.Swift().handleAsyncError(D, AL); 7016fe6060f1SDimitry Andric break; 7017e8d8bef9SDimitry Andric 70180b57cec5SDimitry Andric // XRay attributes. 70190b57cec5SDimitry Andric case ParsedAttr::AT_XRayLogArgs: 70200b57cec5SDimitry Andric handleXRayLogArgsAttr(S, D, AL); 70210b57cec5SDimitry Andric break; 70220b57cec5SDimitry Andric 7023480093f4SDimitry Andric case ParsedAttr::AT_PatchableFunctionEntry: 7024480093f4SDimitry Andric handlePatchableFunctionEntryAttr(S, D, AL); 7025480093f4SDimitry Andric break; 7026480093f4SDimitry Andric 70270b57cec5SDimitry Andric case ParsedAttr::AT_AlwaysDestroy: 70280b57cec5SDimitry Andric case ParsedAttr::AT_NoDestroy: 70290b57cec5SDimitry Andric handleDestroyAttr(S, D, AL); 70300b57cec5SDimitry Andric break; 70310b57cec5SDimitry Andric 70320b57cec5SDimitry Andric case ParsedAttr::AT_Uninitialized: 70330b57cec5SDimitry Andric handleUninitializedAttr(S, D, AL); 70340b57cec5SDimitry Andric break; 70350b57cec5SDimitry Andric 70360b57cec5SDimitry Andric case ParsedAttr::AT_ObjCExternallyRetained: 70370fca6ea1SDimitry Andric S.ObjC().handleExternallyRetainedAttr(D, AL); 70380b57cec5SDimitry Andric break; 70390b57cec5SDimitry Andric 70400b57cec5SDimitry Andric case ParsedAttr::AT_MIGServerRoutine: 70410b57cec5SDimitry Andric handleMIGServerRoutineAttr(S, D, AL); 70420b57cec5SDimitry Andric break; 70430b57cec5SDimitry Andric 70440b57cec5SDimitry Andric case ParsedAttr::AT_MSAllocator: 70450b57cec5SDimitry Andric handleMSAllocatorAttr(S, D, AL); 70460b57cec5SDimitry Andric break; 7047480093f4SDimitry Andric 70485ffd83dbSDimitry Andric case ParsedAttr::AT_ArmBuiltinAlias: 70490fca6ea1SDimitry Andric S.ARM().handleBuiltinAliasAttr(D, AL); 7050480093f4SDimitry Andric break; 7051480093f4SDimitry Andric 70525f757f3fSDimitry Andric case ParsedAttr::AT_ArmLocallyStreaming: 70535f757f3fSDimitry Andric handleSimpleAttribute<ArmLocallyStreamingAttr>(S, D, AL); 70545f757f3fSDimitry Andric break; 70555f757f3fSDimitry Andric 70567a6dacacSDimitry Andric case ParsedAttr::AT_ArmNew: 70570fca6ea1SDimitry Andric S.ARM().handleNewAttr(D, AL); 70585f757f3fSDimitry Andric break; 70595f757f3fSDimitry Andric 7060480093f4SDimitry Andric case ParsedAttr::AT_AcquireHandle: 70615ffd83dbSDimitry Andric handleAcquireHandleAttr(S, D, AL); 7062480093f4SDimitry Andric break; 7063480093f4SDimitry Andric 7064480093f4SDimitry Andric case ParsedAttr::AT_ReleaseHandle: 7065480093f4SDimitry Andric handleHandleAttr<ReleaseHandleAttr>(S, D, AL); 7066480093f4SDimitry Andric break; 7067480093f4SDimitry Andric 706806c3fb27SDimitry Andric case ParsedAttr::AT_UnsafeBufferUsage: 706906c3fb27SDimitry Andric handleUnsafeBufferUsage<UnsafeBufferUsageAttr>(S, D, AL); 707006c3fb27SDimitry Andric break; 707106c3fb27SDimitry Andric 7072480093f4SDimitry Andric case ParsedAttr::AT_UseHandle: 7073480093f4SDimitry Andric handleHandleAttr<UseHandleAttr>(S, D, AL); 7074480093f4SDimitry Andric break; 7075e8d8bef9SDimitry Andric 7076e8d8bef9SDimitry Andric case ParsedAttr::AT_EnforceTCB: 7077e8d8bef9SDimitry Andric handleEnforceTCBAttr<EnforceTCBAttr, EnforceTCBLeafAttr>(S, D, AL); 7078e8d8bef9SDimitry Andric break; 7079e8d8bef9SDimitry Andric 7080e8d8bef9SDimitry Andric case ParsedAttr::AT_EnforceTCBLeaf: 7081e8d8bef9SDimitry Andric handleEnforceTCBAttr<EnforceTCBLeafAttr, EnforceTCBAttr>(S, D, AL); 7082e8d8bef9SDimitry Andric break; 7083fe6060f1SDimitry Andric 7084fe6060f1SDimitry Andric case ParsedAttr::AT_BuiltinAlias: 7085fe6060f1SDimitry Andric handleBuiltinAliasAttr(S, D, AL); 7086fe6060f1SDimitry Andric break; 7087fe6060f1SDimitry Andric 70885f757f3fSDimitry Andric case ParsedAttr::AT_PreferredType: 70895f757f3fSDimitry Andric handlePreferredTypeAttr(S, D, AL); 70905f757f3fSDimitry Andric break; 70915f757f3fSDimitry Andric 7092fe6060f1SDimitry Andric case ParsedAttr::AT_UsingIfExists: 7093fe6060f1SDimitry Andric handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL); 7094fe6060f1SDimitry Andric break; 70950fca6ea1SDimitry Andric 70960fca6ea1SDimitry Andric case ParsedAttr::AT_TypeNullable: 70970fca6ea1SDimitry Andric handleNullableTypeAttr(S, D, AL); 70980fca6ea1SDimitry Andric break; 70990fca6ea1SDimitry Andric 71000fca6ea1SDimitry Andric case ParsedAttr::AT_VTablePointerAuthentication: 71010fca6ea1SDimitry Andric handleVTablePointerAuthentication(S, D, AL); 71020fca6ea1SDimitry Andric break; 71030b57cec5SDimitry Andric } 71040b57cec5SDimitry Andric } 71050b57cec5SDimitry Andric 710681ad6265SDimitry Andric void Sema::ProcessDeclAttributeList( 710781ad6265SDimitry Andric Scope *S, Decl *D, const ParsedAttributesView &AttrList, 710881ad6265SDimitry Andric const ProcessDeclAttributeOptions &Options) { 71090b57cec5SDimitry Andric if (AttrList.empty()) 71100b57cec5SDimitry Andric return; 71110b57cec5SDimitry Andric 71120b57cec5SDimitry Andric for (const ParsedAttr &AL : AttrList) 711381ad6265SDimitry Andric ProcessDeclAttribute(*this, S, D, AL, Options); 71140b57cec5SDimitry Andric 71150b57cec5SDimitry Andric // FIXME: We should be able to handle these cases in TableGen. 71160b57cec5SDimitry Andric // GCC accepts 71170b57cec5SDimitry Andric // static int a9 __attribute__((weakref)); 71180b57cec5SDimitry Andric // but that looks really pointless. We reject it. 71190b57cec5SDimitry Andric if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { 71200b57cec5SDimitry Andric Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias) 71210b57cec5SDimitry Andric << cast<NamedDecl>(D); 71220b57cec5SDimitry Andric D->dropAttr<WeakRefAttr>(); 71230b57cec5SDimitry Andric return; 71240b57cec5SDimitry Andric } 71250b57cec5SDimitry Andric 71260b57cec5SDimitry Andric // FIXME: We should be able to handle this in TableGen as well. It would be 71270b57cec5SDimitry Andric // good to have a way to specify "these attributes must appear as a group", 71280b57cec5SDimitry Andric // for these. Additionally, it would be good to have a way to specify "these 71290b57cec5SDimitry Andric // attribute must never appear as a group" for attributes like cold and hot. 71300b57cec5SDimitry Andric if (!D->hasAttr<OpenCLKernelAttr>()) { 71310b57cec5SDimitry Andric // These attributes cannot be applied to a non-kernel function. 71320b57cec5SDimitry Andric if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) { 71330b57cec5SDimitry Andric // FIXME: This emits a different error message than 71340b57cec5SDimitry Andric // diag::err_attribute_wrong_decl_type + ExpectedKernelFunction. 71350b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; 71360b57cec5SDimitry Andric D->setInvalidDecl(); 71370b57cec5SDimitry Andric } else if (const auto *A = D->getAttr<WorkGroupSizeHintAttr>()) { 71380b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; 71390b57cec5SDimitry Andric D->setInvalidDecl(); 71400b57cec5SDimitry Andric } else if (const auto *A = D->getAttr<VecTypeHintAttr>()) { 71410b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; 71420b57cec5SDimitry Andric D->setInvalidDecl(); 71430b57cec5SDimitry Andric } else if (const auto *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) { 71440b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; 71450b57cec5SDimitry Andric D->setInvalidDecl(); 71460b57cec5SDimitry Andric } else if (!D->hasAttr<CUDAGlobalAttr>()) { 71470b57cec5SDimitry Andric if (const auto *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) { 71480b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) 714906c3fb27SDimitry Andric << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; 71500b57cec5SDimitry Andric D->setInvalidDecl(); 71510b57cec5SDimitry Andric } else if (const auto *A = D->getAttr<AMDGPUWavesPerEUAttr>()) { 71520b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) 715306c3fb27SDimitry Andric << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; 71540b57cec5SDimitry Andric D->setInvalidDecl(); 71550b57cec5SDimitry Andric } else if (const auto *A = D->getAttr<AMDGPUNumSGPRAttr>()) { 71560b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) 715706c3fb27SDimitry Andric << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; 71580b57cec5SDimitry Andric D->setInvalidDecl(); 71590b57cec5SDimitry Andric } else if (const auto *A = D->getAttr<AMDGPUNumVGPRAttr>()) { 71600b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) 716106c3fb27SDimitry Andric << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; 71620b57cec5SDimitry Andric D->setInvalidDecl(); 71630b57cec5SDimitry Andric } 71640b57cec5SDimitry Andric } 71650b57cec5SDimitry Andric } 71660b57cec5SDimitry Andric 71670b57cec5SDimitry Andric // Do this check after processing D's attributes because the attribute 71680b57cec5SDimitry Andric // objc_method_family can change whether the given method is in the init 71690b57cec5SDimitry Andric // family, and it can be applied after objc_designated_initializer. This is a 71700b57cec5SDimitry Andric // bit of a hack, but we need it to be compatible with versions of clang that 71710b57cec5SDimitry Andric // processed the attribute list in the wrong order. 71720b57cec5SDimitry Andric if (D->hasAttr<ObjCDesignatedInitializerAttr>() && 71730b57cec5SDimitry Andric cast<ObjCMethodDecl>(D)->getMethodFamily() != OMF_init) { 71740b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_designated_init_attr_non_init); 71750b57cec5SDimitry Andric D->dropAttr<ObjCDesignatedInitializerAttr>(); 71760b57cec5SDimitry Andric } 71770b57cec5SDimitry Andric } 71780b57cec5SDimitry Andric 71790b57cec5SDimitry Andric void Sema::ProcessDeclAttributeDelayed(Decl *D, 71800b57cec5SDimitry Andric const ParsedAttributesView &AttrList) { 71810b57cec5SDimitry Andric for (const ParsedAttr &AL : AttrList) 71820b57cec5SDimitry Andric if (AL.getKind() == ParsedAttr::AT_TransparentUnion) { 71830b57cec5SDimitry Andric handleTransparentUnionAttr(*this, D, AL); 71840b57cec5SDimitry Andric break; 71850b57cec5SDimitry Andric } 7186480093f4SDimitry Andric 7187480093f4SDimitry Andric // For BPFPreserveAccessIndexAttr, we want to populate the attributes 7188480093f4SDimitry Andric // to fields and inner records as well. 7189480093f4SDimitry Andric if (D && D->hasAttr<BPFPreserveAccessIndexAttr>()) 71900fca6ea1SDimitry Andric BPF().handlePreserveAIRecord(cast<RecordDecl>(D)); 71910b57cec5SDimitry Andric } 71920b57cec5SDimitry Andric 71930b57cec5SDimitry Andric bool Sema::ProcessAccessDeclAttributeList( 71940b57cec5SDimitry Andric AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) { 71950b57cec5SDimitry Andric for (const ParsedAttr &AL : AttrList) { 71960b57cec5SDimitry Andric if (AL.getKind() == ParsedAttr::AT_Annotate) { 719781ad6265SDimitry Andric ProcessDeclAttribute(*this, nullptr, ASDecl, AL, 719881ad6265SDimitry Andric ProcessDeclAttributeOptions()); 71990b57cec5SDimitry Andric } else { 72000b57cec5SDimitry Andric Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec); 72010b57cec5SDimitry Andric return true; 72020b57cec5SDimitry Andric } 72030b57cec5SDimitry Andric } 72040b57cec5SDimitry Andric return false; 72050b57cec5SDimitry Andric } 72060b57cec5SDimitry Andric 72070b57cec5SDimitry Andric /// checkUnusedDeclAttributes - Check a list of attributes to see if it 72080b57cec5SDimitry Andric /// contains any decl attributes that we should warn about. 72090b57cec5SDimitry Andric static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { 72100b57cec5SDimitry Andric for (const ParsedAttr &AL : A) { 72110b57cec5SDimitry Andric // Only warn if the attribute is an unignored, non-type attribute. 72120b57cec5SDimitry Andric if (AL.isUsedAsTypeAttr() || AL.isInvalid()) 72130b57cec5SDimitry Andric continue; 72140b57cec5SDimitry Andric if (AL.getKind() == ParsedAttr::IgnoredAttribute) 72150b57cec5SDimitry Andric continue; 72160b57cec5SDimitry Andric 72170b57cec5SDimitry Andric if (AL.getKind() == ParsedAttr::UnknownAttribute) { 72180b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) 72190b57cec5SDimitry Andric << AL << AL.getRange(); 72200b57cec5SDimitry Andric } else { 72210b57cec5SDimitry Andric S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) << AL 72220b57cec5SDimitry Andric << AL.getRange(); 72230b57cec5SDimitry Andric } 72240b57cec5SDimitry Andric } 72250b57cec5SDimitry Andric } 72260b57cec5SDimitry Andric 72270b57cec5SDimitry Andric void Sema::checkUnusedDeclAttributes(Declarator &D) { 722881ad6265SDimitry Andric ::checkUnusedDeclAttributes(*this, D.getDeclarationAttributes()); 72290b57cec5SDimitry Andric ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes()); 72300b57cec5SDimitry Andric ::checkUnusedDeclAttributes(*this, D.getAttributes()); 72310b57cec5SDimitry Andric for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) 72320b57cec5SDimitry Andric ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); 72330b57cec5SDimitry Andric } 72340b57cec5SDimitry Andric 723581ad6265SDimitry Andric NamedDecl *Sema::DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II, 72360b57cec5SDimitry Andric SourceLocation Loc) { 72370b57cec5SDimitry Andric assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND)); 72380b57cec5SDimitry Andric NamedDecl *NewD = nullptr; 72390b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(ND)) { 72400b57cec5SDimitry Andric FunctionDecl *NewFD; 72410b57cec5SDimitry Andric // FIXME: Missing call to CheckFunctionDeclaration(). 72420b57cec5SDimitry Andric // FIXME: Mangling? 72430b57cec5SDimitry Andric // FIXME: Is the qualifier info correct? 72440b57cec5SDimitry Andric // FIXME: Is the DeclContext correct? 72450b57cec5SDimitry Andric NewFD = FunctionDecl::Create( 72460b57cec5SDimitry Andric FD->getASTContext(), FD->getDeclContext(), Loc, Loc, 72470b57cec5SDimitry Andric DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None, 7248349cc55cSDimitry Andric getCurFPFeatures().isFPConstrained(), false /*isInlineSpecified*/, 7249349cc55cSDimitry Andric FD->hasPrototype(), ConstexprSpecKind::Unspecified, 7250349cc55cSDimitry Andric FD->getTrailingRequiresClause()); 72510b57cec5SDimitry Andric NewD = NewFD; 72520b57cec5SDimitry Andric 72530b57cec5SDimitry Andric if (FD->getQualifier()) 72540b57cec5SDimitry Andric NewFD->setQualifierInfo(FD->getQualifierLoc()); 72550b57cec5SDimitry Andric 72560b57cec5SDimitry Andric // Fake up parameter variables; they are declared as if this were 72570b57cec5SDimitry Andric // a typedef. 72580b57cec5SDimitry Andric QualType FDTy = FD->getType(); 72590b57cec5SDimitry Andric if (const auto *FT = FDTy->getAs<FunctionProtoType>()) { 72600b57cec5SDimitry Andric SmallVector<ParmVarDecl*, 16> Params; 72610b57cec5SDimitry Andric for (const auto &AI : FT->param_types()) { 72620b57cec5SDimitry Andric ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI); 72630b57cec5SDimitry Andric Param->setScopeInfo(0, Params.size()); 72640b57cec5SDimitry Andric Params.push_back(Param); 72650b57cec5SDimitry Andric } 72660b57cec5SDimitry Andric NewFD->setParams(Params); 72670b57cec5SDimitry Andric } 72680b57cec5SDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(ND)) { 72690b57cec5SDimitry Andric NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), 72700b57cec5SDimitry Andric VD->getInnerLocStart(), VD->getLocation(), II, 72710b57cec5SDimitry Andric VD->getType(), VD->getTypeSourceInfo(), 72720b57cec5SDimitry Andric VD->getStorageClass()); 72730b57cec5SDimitry Andric if (VD->getQualifier()) 72740b57cec5SDimitry Andric cast<VarDecl>(NewD)->setQualifierInfo(VD->getQualifierLoc()); 72750b57cec5SDimitry Andric } 72760b57cec5SDimitry Andric return NewD; 72770b57cec5SDimitry Andric } 72780b57cec5SDimitry Andric 727981ad6265SDimitry Andric void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W) { 72800b57cec5SDimitry Andric if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) 72810b57cec5SDimitry Andric IdentifierInfo *NDId = ND->getIdentifier(); 72820b57cec5SDimitry Andric NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation()); 7283a7dea167SDimitry Andric NewD->addAttr( 7284a7dea167SDimitry Andric AliasAttr::CreateImplicit(Context, NDId->getName(), W.getLocation())); 728506c3fb27SDimitry Andric NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation())); 72860b57cec5SDimitry Andric WeakTopLevelDecl.push_back(NewD); 72870b57cec5SDimitry Andric // FIXME: "hideous" code from Sema::LazilyCreateBuiltin 72880b57cec5SDimitry Andric // to insert Decl at TU scope, sorry. 72890b57cec5SDimitry Andric DeclContext *SavedContext = CurContext; 72900b57cec5SDimitry Andric CurContext = Context.getTranslationUnitDecl(); 72910b57cec5SDimitry Andric NewD->setDeclContext(CurContext); 72920b57cec5SDimitry Andric NewD->setLexicalDeclContext(CurContext); 72930b57cec5SDimitry Andric PushOnScopeChains(NewD, S); 72940b57cec5SDimitry Andric CurContext = SavedContext; 72950b57cec5SDimitry Andric } else { // just add weak to existing 729606c3fb27SDimitry Andric ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation())); 72970b57cec5SDimitry Andric } 72980b57cec5SDimitry Andric } 72990b57cec5SDimitry Andric 73000b57cec5SDimitry Andric void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { 73010b57cec5SDimitry Andric // It's valid to "forward-declare" #pragma weak, in which case we 73020b57cec5SDimitry Andric // have to do this. 73030b57cec5SDimitry Andric LoadExternalWeakUndeclaredIdentifiers(); 730481ad6265SDimitry Andric if (WeakUndeclaredIdentifiers.empty()) 730581ad6265SDimitry Andric return; 73060b57cec5SDimitry Andric NamedDecl *ND = nullptr; 73070b57cec5SDimitry Andric if (auto *VD = dyn_cast<VarDecl>(D)) 73080b57cec5SDimitry Andric if (VD->isExternC()) 73090b57cec5SDimitry Andric ND = VD; 73100b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(D)) 73110b57cec5SDimitry Andric if (FD->isExternC()) 73120b57cec5SDimitry Andric ND = FD; 731381ad6265SDimitry Andric if (!ND) 731481ad6265SDimitry Andric return; 73150b57cec5SDimitry Andric if (IdentifierInfo *Id = ND->getIdentifier()) { 73160b57cec5SDimitry Andric auto I = WeakUndeclaredIdentifiers.find(Id); 73170b57cec5SDimitry Andric if (I != WeakUndeclaredIdentifiers.end()) { 731881ad6265SDimitry Andric auto &WeakInfos = I->second; 731981ad6265SDimitry Andric for (const auto &W : WeakInfos) 73200b57cec5SDimitry Andric DeclApplyPragmaWeak(S, ND, W); 732181ad6265SDimitry Andric std::remove_reference_t<decltype(WeakInfos)> EmptyWeakInfos; 732281ad6265SDimitry Andric WeakInfos.swap(EmptyWeakInfos); 73230b57cec5SDimitry Andric } 73240b57cec5SDimitry Andric } 73250b57cec5SDimitry Andric } 73260b57cec5SDimitry Andric 73270b57cec5SDimitry Andric /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in 73280b57cec5SDimitry Andric /// it, apply them to D. This is a bit tricky because PD can have attributes 73290b57cec5SDimitry Andric /// specified in many different places, and we need to find and apply them all. 73300b57cec5SDimitry Andric void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { 733181ad6265SDimitry Andric // Ordering of attributes can be important, so we take care to process 733281ad6265SDimitry Andric // attributes in the order in which they appeared in the source code. 733381ad6265SDimitry Andric 73340fca6ea1SDimitry Andric auto ProcessAttributesWithSliding = 73350fca6ea1SDimitry Andric [&](const ParsedAttributesView &Src, 73360fca6ea1SDimitry Andric const ProcessDeclAttributeOptions &Options) { 733781ad6265SDimitry Andric ParsedAttributesView NonSlidingAttrs; 73380fca6ea1SDimitry Andric for (ParsedAttr &AL : Src) { 73390fca6ea1SDimitry Andric // FIXME: this sliding is specific to standard attributes and should 73400fca6ea1SDimitry Andric // eventually be deprecated and removed as those are not intended to 73410fca6ea1SDimitry Andric // slide to anything. 73420fca6ea1SDimitry Andric if ((AL.isStandardAttributeSyntax() || AL.isAlignas()) && 73430fca6ea1SDimitry Andric AL.slidesFromDeclToDeclSpecLegacyBehavior()) { 73440fca6ea1SDimitry Andric // Skip processing the attribute, but do check if it appertains to 73450fca6ea1SDimitry Andric // the declaration. This is needed for the `MatrixType` attribute, 73460fca6ea1SDimitry Andric // which, despite being a type attribute, defines a `SubjectList` 73470fca6ea1SDimitry Andric // that only allows it to be used on typedef declarations. 734881ad6265SDimitry Andric AL.diagnoseAppertainsTo(*this, D); 734981ad6265SDimitry Andric } else { 735081ad6265SDimitry Andric NonSlidingAttrs.addAtEnd(&AL); 735181ad6265SDimitry Andric } 735281ad6265SDimitry Andric } 73530fca6ea1SDimitry Andric ProcessDeclAttributeList(S, D, NonSlidingAttrs, Options); 73540fca6ea1SDimitry Andric }; 73550fca6ea1SDimitry Andric 73560fca6ea1SDimitry Andric // First, process attributes that appeared on the declaration itself (but 73570fca6ea1SDimitry Andric // only if they don't have the legacy behavior of "sliding" to the DeclSepc). 73580fca6ea1SDimitry Andric ProcessAttributesWithSliding(PD.getDeclarationAttributes(), {}); 735981ad6265SDimitry Andric 73600b57cec5SDimitry Andric // Apply decl attributes from the DeclSpec if present. 73610fca6ea1SDimitry Andric ProcessAttributesWithSliding(PD.getDeclSpec().getAttributes(), 736281ad6265SDimitry Andric ProcessDeclAttributeOptions() 736381ad6265SDimitry Andric .WithIncludeCXX11Attributes(false) 736481ad6265SDimitry Andric .WithIgnoreTypeAttributes(true)); 73650b57cec5SDimitry Andric 73660b57cec5SDimitry Andric // Walk the declarator structure, applying decl attributes that were in a type 73670b57cec5SDimitry Andric // position to the decl itself. This handles cases like: 73680b57cec5SDimitry Andric // int *__attr__(x)** D; 73690b57cec5SDimitry Andric // when X is a decl attribute. 737081ad6265SDimitry Andric for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) { 73710b57cec5SDimitry Andric ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(), 737281ad6265SDimitry Andric ProcessDeclAttributeOptions() 737381ad6265SDimitry Andric .WithIncludeCXX11Attributes(false) 737481ad6265SDimitry Andric .WithIgnoreTypeAttributes(true)); 737581ad6265SDimitry Andric } 73760b57cec5SDimitry Andric 73770b57cec5SDimitry Andric // Finally, apply any attributes on the decl itself. 73780b57cec5SDimitry Andric ProcessDeclAttributeList(S, D, PD.getAttributes()); 73790b57cec5SDimitry Andric 73800b57cec5SDimitry Andric // Apply additional attributes specified by '#pragma clang attribute'. 73810b57cec5SDimitry Andric AddPragmaAttributes(S, D); 73820fca6ea1SDimitry Andric 73830fca6ea1SDimitry Andric // Look for API notes that map to attributes. 73840fca6ea1SDimitry Andric ProcessAPINotes(D); 73850b57cec5SDimitry Andric } 73860b57cec5SDimitry Andric 73870b57cec5SDimitry Andric /// Is the given declaration allowed to use a forbidden type? 73880b57cec5SDimitry Andric /// If so, it'll still be annotated with an attribute that makes it 73890b57cec5SDimitry Andric /// illegal to actually use. 73900b57cec5SDimitry Andric static bool isForbiddenTypeAllowed(Sema &S, Decl *D, 73910b57cec5SDimitry Andric const DelayedDiagnostic &diag, 73920b57cec5SDimitry Andric UnavailableAttr::ImplicitReason &reason) { 73930b57cec5SDimitry Andric // Private ivars are always okay. Unfortunately, people don't 73940b57cec5SDimitry Andric // always properly make their ivars private, even in system headers. 73950b57cec5SDimitry Andric // Plus we need to make fields okay, too. 73960b57cec5SDimitry Andric if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) && 73970b57cec5SDimitry Andric !isa<FunctionDecl>(D)) 73980b57cec5SDimitry Andric return false; 73990b57cec5SDimitry Andric 74000b57cec5SDimitry Andric // Silently accept unsupported uses of __weak in both user and system 74010b57cec5SDimitry Andric // declarations when it's been disabled, for ease of integration with 74020b57cec5SDimitry Andric // -fno-objc-arc files. We do have to take some care against attempts 74030b57cec5SDimitry Andric // to define such things; for now, we've only done that for ivars 74040b57cec5SDimitry Andric // and properties. 74050b57cec5SDimitry Andric if ((isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D))) { 74060b57cec5SDimitry Andric if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled || 74070b57cec5SDimitry Andric diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) { 74080b57cec5SDimitry Andric reason = UnavailableAttr::IR_ForbiddenWeak; 74090b57cec5SDimitry Andric return true; 74100b57cec5SDimitry Andric } 74110b57cec5SDimitry Andric } 74120b57cec5SDimitry Andric 74130b57cec5SDimitry Andric // Allow all sorts of things in system headers. 74140b57cec5SDimitry Andric if (S.Context.getSourceManager().isInSystemHeader(D->getLocation())) { 74150b57cec5SDimitry Andric // Currently, all the failures dealt with this way are due to ARC 74160b57cec5SDimitry Andric // restrictions. 74170b57cec5SDimitry Andric reason = UnavailableAttr::IR_ARCForbiddenType; 74180b57cec5SDimitry Andric return true; 74190b57cec5SDimitry Andric } 74200b57cec5SDimitry Andric 74210b57cec5SDimitry Andric return false; 74220b57cec5SDimitry Andric } 74230b57cec5SDimitry Andric 74240b57cec5SDimitry Andric /// Handle a delayed forbidden-type diagnostic. 74250b57cec5SDimitry Andric static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &DD, 74260b57cec5SDimitry Andric Decl *D) { 74270b57cec5SDimitry Andric auto Reason = UnavailableAttr::IR_None; 74280b57cec5SDimitry Andric if (D && isForbiddenTypeAllowed(S, D, DD, Reason)) { 74290b57cec5SDimitry Andric assert(Reason && "didn't set reason?"); 74300b57cec5SDimitry Andric D->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", Reason, DD.Loc)); 74310b57cec5SDimitry Andric return; 74320b57cec5SDimitry Andric } 74330b57cec5SDimitry Andric if (S.getLangOpts().ObjCAutoRefCount) 74340b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 74350b57cec5SDimitry Andric // FIXME: we may want to suppress diagnostics for all 74360b57cec5SDimitry Andric // kind of forbidden type messages on unavailable functions. 74370b57cec5SDimitry Andric if (FD->hasAttr<UnavailableAttr>() && 74380b57cec5SDimitry Andric DD.getForbiddenTypeDiagnostic() == 74390b57cec5SDimitry Andric diag::err_arc_array_param_no_ownership) { 74400b57cec5SDimitry Andric DD.Triggered = true; 74410b57cec5SDimitry Andric return; 74420b57cec5SDimitry Andric } 74430b57cec5SDimitry Andric } 74440b57cec5SDimitry Andric 74450b57cec5SDimitry Andric S.Diag(DD.Loc, DD.getForbiddenTypeDiagnostic()) 74460b57cec5SDimitry Andric << DD.getForbiddenTypeOperand() << DD.getForbiddenTypeArgument(); 74470b57cec5SDimitry Andric DD.Triggered = true; 74480b57cec5SDimitry Andric } 74490b57cec5SDimitry Andric 74500b57cec5SDimitry Andric 74510b57cec5SDimitry Andric void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { 74520b57cec5SDimitry Andric assert(DelayedDiagnostics.getCurrentPool()); 74530b57cec5SDimitry Andric DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool(); 74540b57cec5SDimitry Andric DelayedDiagnostics.popWithoutEmitting(state); 74550b57cec5SDimitry Andric 74560b57cec5SDimitry Andric // When delaying diagnostics to run in the context of a parsed 74570b57cec5SDimitry Andric // declaration, we only want to actually emit anything if parsing 74580b57cec5SDimitry Andric // succeeds. 74590b57cec5SDimitry Andric if (!decl) return; 74600b57cec5SDimitry Andric 74610b57cec5SDimitry Andric // We emit all the active diagnostics in this pool or any of its 74620b57cec5SDimitry Andric // parents. In general, we'll get one pool for the decl spec 74630b57cec5SDimitry Andric // and a child pool for each declarator; in a decl group like: 74640b57cec5SDimitry Andric // deprecated_typedef foo, *bar, baz(); 74650b57cec5SDimitry Andric // only the declarator pops will be passed decls. This is correct; 74660b57cec5SDimitry Andric // we really do need to consider delayed diagnostics from the decl spec 74670b57cec5SDimitry Andric // for each of the different declarations. 74680b57cec5SDimitry Andric const DelayedDiagnosticPool *pool = &poppedPool; 74690b57cec5SDimitry Andric do { 74700b57cec5SDimitry Andric bool AnyAccessFailures = false; 74710b57cec5SDimitry Andric for (DelayedDiagnosticPool::pool_iterator 74720b57cec5SDimitry Andric i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) { 74730b57cec5SDimitry Andric // This const_cast is a bit lame. Really, Triggered should be mutable. 74740b57cec5SDimitry Andric DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i); 74750b57cec5SDimitry Andric if (diag.Triggered) 74760b57cec5SDimitry Andric continue; 74770b57cec5SDimitry Andric 74780b57cec5SDimitry Andric switch (diag.Kind) { 74790b57cec5SDimitry Andric case DelayedDiagnostic::Availability: 74800b57cec5SDimitry Andric // Don't bother giving deprecation/unavailable diagnostics if 74810b57cec5SDimitry Andric // the decl is invalid. 74820b57cec5SDimitry Andric if (!decl->isInvalidDecl()) 74835ffd83dbSDimitry Andric handleDelayedAvailabilityCheck(diag, decl); 74840b57cec5SDimitry Andric break; 74850b57cec5SDimitry Andric 74860b57cec5SDimitry Andric case DelayedDiagnostic::Access: 74870b57cec5SDimitry Andric // Only produce one access control diagnostic for a structured binding 74880b57cec5SDimitry Andric // declaration: we don't need to tell the user that all the fields are 74890b57cec5SDimitry Andric // inaccessible one at a time. 74900b57cec5SDimitry Andric if (AnyAccessFailures && isa<DecompositionDecl>(decl)) 74910b57cec5SDimitry Andric continue; 74920b57cec5SDimitry Andric HandleDelayedAccessCheck(diag, decl); 74930b57cec5SDimitry Andric if (diag.Triggered) 74940b57cec5SDimitry Andric AnyAccessFailures = true; 74950b57cec5SDimitry Andric break; 74960b57cec5SDimitry Andric 74970b57cec5SDimitry Andric case DelayedDiagnostic::ForbiddenType: 74980b57cec5SDimitry Andric handleDelayedForbiddenType(*this, diag, decl); 74990b57cec5SDimitry Andric break; 75000b57cec5SDimitry Andric } 75010b57cec5SDimitry Andric } 75020b57cec5SDimitry Andric } while ((pool = pool->getParent())); 75030b57cec5SDimitry Andric } 75040b57cec5SDimitry Andric 75050b57cec5SDimitry Andric void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) { 75060b57cec5SDimitry Andric DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool(); 75070b57cec5SDimitry Andric assert(curPool && "re-emitting in undelayed context not supported"); 75080b57cec5SDimitry Andric curPool->steal(pool); 75090b57cec5SDimitry Andric } 7510