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
getNumAttributeArgs(const ParsedAttr & AL)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
getAttrLoc(const ParsedAttr & AL)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>
checkPositiveIntArgument(Sema & S,const AttrInfo & AI,const Expr * Expr,int & Val,unsigned Idx=UINT_MAX)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
checkStringLiteralArgumentAttr(const AttributeCommonInfo & CI,const Expr * E,StringRef & Str,SourceLocation * ArgLocation)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
checkStringLiteralArgumentAttr(const ParsedAttr & AL,unsigned ArgNum,StringRef & Str,SourceLocation * ArgLocation)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.
isIntOrBool(Expr * Exp)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*.
threadSafetyCheckIsSmartPointer(Sema & S,const RecordType * RT)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
threadSafetyCheckIsPointer(Sema & S,const Decl * D,const ParsedAttr & AL)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.
getRecordType(QualType QT)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>
checkRecordDeclForAttr(const RecordDecl * RD)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
checkRecordTypeForCapability(Sema & S,QualType Ty)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
checkTypedefTypeForCapability(QualType Ty)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
typeHasCapability(Sema & S,QualType Ty)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
isCapabilityExpr(Sema & S,const Expr * Ex)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.
checkAttrArgsAreCapabilityObjs(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args,unsigned Sidx=0,bool ParamIdxOk=false)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
handlePtGuardedVarAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
checkGuardedByAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,Expr * & Arg)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
handleGuardedByAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handlePtGuardedByAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
checkAcquireOrderAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)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
handleAcquiredAfterAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAcquiredBeforeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
checkLockFunAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)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
handleAssertSharedLockAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAssertExclusiveLockAttr(Sema & S,Decl * D,const ParsedAttr & AL)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>
checkParamIsIntegerType(Sema & S,const Decl * D,const AttrInfo & AI,unsigned AttrArgNo)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
handleAllocSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
checkTryLockFunAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)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
handleSharedTrylockFunctionAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleExclusiveTrylockFunctionAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleLockReturnedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleLocksExcludedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
checkFunctionConditionAttr(Sema & S,Decl * D,const ParsedAttr & AL,Expr * & Cond,StringRef & Msg)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
handleEnableIfAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleErrorAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleExcludeFromExplicitInstantiationAttr(Sema & S,Decl * D,const ParsedAttr & AL)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:
ArgumentDependenceChecker(const FunctionDecl * FD)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
referencesArgs(Expr * E)7450b57cec5SDimitry Andric bool referencesArgs(Expr *E) {
7460b57cec5SDimitry Andric Result = false;
7470b57cec5SDimitry Andric TraverseStmt(E);
7480b57cec5SDimitry Andric return Result;
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric
VisitCXXThisExpr(CXXThisExpr * E)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
VisitDeclRefExpr(DeclRefExpr * DRE)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
handleDiagnoseAsBuiltinAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleDiagnoseIfAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNoBuiltinAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handlePassObjectSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleConsumableAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
checkForConsumableClass(Sema & S,const CXXMethodDecl * MD,const ParsedAttr & AL)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
handleCallableWhenAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleParamTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleReturnTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleSetTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleTestTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleExtVectorTypeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handlePackedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handlePreferredName(Sema & S,Decl * D,const ParsedAttr & AL)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
isValidPointerAttrType(QualType T,bool RefOkay)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
attrNonNullArgCheck(Sema & S,QualType T,const ParsedAttr & AL,SourceRange AttrParmRange,SourceRange TypeRange,bool isReturnValue=false)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
handleNonNullAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNonNullAttrParameter(Sema & S,ParmVarDecl * D,const ParsedAttr & AL)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
handleReturnsNonNullAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNoEscapeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAssumeAlignedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAllocAlignAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
AddAssumeAlignedAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E,Expr * OE)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
AddAllocAlignAttr(Decl * D,const AttributeCommonInfo & CI,Expr * ParamExpr)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.
normalizeName(StringRef & AttrName)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
handleOwnershipAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleWeakRefAttr(Sema & S,Decl * D,const ParsedAttr & AL)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.
markUsedForAliasOrIfunc(Sema & S,Decl * D,const ParsedAttr & AL,StringRef Str)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
handleIFuncAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAliasAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleTLSModelAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleRestrictAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleCPUSpecificAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleCommonAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNakedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNoReturnAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)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
handleStandardNoReturnAttr(Sema & S,Decl * D,const ParsedAttr & A)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
handleNoCfCheckAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)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
CheckAttrNoArgs(const ParsedAttr & Attrs)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
CheckAttrTarget(const ParsedAttr & AL)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
handleAnalyzerNoReturnAttr(Sema & S,Decl * D,const ParsedAttr & AL)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.
handleVecReturnAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleDependencyAttr(Sema & S,Scope * Scope,Decl * D,const ParsedAttr & AL)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
handleUnusedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleConstructorAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleDestructorAttr(Sema & S,Decl * D,const ParsedAttr & AL)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>
handleAttrWithMessage(Sema & S,Decl * D,const ParsedAttr & AL)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
checkAvailabilityAttr(Sema & S,SourceRange Range,IdentifierInfo * Platform,VersionTuple Introduced,VersionTuple Deprecated,VersionTuple Obsoleted)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.
versionsMatch(const VersionTuple & X,const VersionTuple & Y,bool BeforeIsOkay)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
mergeAvailabilityAttr(NamedDecl * D,const AttributeCommonInfo & CI,IdentifierInfo * Platform,bool Implicit,VersionTuple Introduced,VersionTuple Deprecated,VersionTuple Obsoleted,bool IsUnavailable,StringRef Message,bool IsStrict,StringRef Replacement,AvailabilityMergeKind AMK,int Priority,IdentifierInfo * Environment)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
handleAvailabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleExternalSourceSymbolAttr(Sema & S,Decl * D,const ParsedAttr & AL)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>
mergeVisibilityAttr(Sema & S,Decl * D,const AttributeCommonInfo & CI,typename T::VisibilityType value)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
mergeVisibilityAttr(Decl * D,const AttributeCommonInfo & CI,VisibilityAttr::VisibilityType Vis)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 *
mergeTypeVisibilityAttr(Decl * D,const AttributeCommonInfo & CI,TypeVisibilityAttr::VisibilityType Vis)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
handleVisibilityAttr(Sema & S,Decl * D,const ParsedAttr & AL,bool isTypeVisibility)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
handleSentinelAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleWarnUnusedResult(Sema & S,Decl * D,const ParsedAttr & AL)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
handleWeakImportAttr(Sema & S,Decl * D,const ParsedAttr & AL)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>
handleWorkGroupSize(Sema & S,Decl * D,const ParsedAttr & AL)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
handleVecTypeHint(Sema & S,Decl * D,const ParsedAttr & AL)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
mergeSectionAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Name)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
isValidSectionSpecifier(StringRef SecName)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
checkSectionName(SourceLocation LiteralLoc,StringRef SecName)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
handleSectionAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleCodeModelAttr(Sema & S,Decl * D,const ParsedAttr & AL)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.
checkCodeSegName(Sema & S,SourceLocation LiteralLoc,StringRef CodeSegName)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
mergeCodeSegAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Name)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
handleCodeSegAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
checkTargetAttr(SourceLocation LiteralLoc,StringRef AttrStr)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
checkTargetVersionAttr(SourceLocation LiteralLoc,Decl * D,StringRef AttrStr)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
handleTargetVersionAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleTargetAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
checkTargetClonesAttrString(SourceLocation LiteralLoc,StringRef Str,const StringLiteral * Literal,Decl * D,bool & HasDefault,bool & HasCommas,bool & HasNotDefault,SmallVectorImpl<SmallString<64>> & StringsBuffer)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
handleTargetClonesAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleMinVectorWidthAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleCleanupAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleEnumExtensibilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleFormatArgAttr(Sema & S,Decl * D,const ParsedAttr & AL)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.
getFormatAttrKind(StringRef Format)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
handleInitPriorityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
mergeErrorAttr(Decl * D,const AttributeCommonInfo & CI,StringRef NewUserDiagnostic)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
mergeFormatAttr(Decl * D,const AttributeCommonInfo & CI,IdentifierInfo * Format,int FormatIdx,int FirstArg)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
handleFormatAttr(Sema & S,Decl * D,const ParsedAttr & AL)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.
handleCallbackAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
isFunctionLike(const Type & T)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.
handleCalledOnceAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleTransparentUnionAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
AddAnnotationAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Str,MutableArrayRef<Expr * > Args)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
handleAnnotateAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAlignValueAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
AddAlignValueAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E)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
handleAlignedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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.
validateAlignasAppliedType(Sema & S,Decl * D,const AlignedAttr & Attr,SourceLocation AttrLoc)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
AddAlignedAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E,bool IsPackExpansion)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
AddAlignedAttr(Decl * D,const AttributeCommonInfo & CI,TypeSourceInfo * TS,bool IsPackExpansion)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
CheckAlignasUnderalignment(Decl * D)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
checkMSInheritanceAttrOnDefinition(CXXRecordDecl * RD,SourceRange Range,bool BestCase,MSInheritanceModel ExplicitModel)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.
parseModeAttrArg(Sema & S,StringRef Str,unsigned & DestWidth,bool & IntegerMode,bool & ComplexMode,FloatModeKind & ExplicitType)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.
handleModeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
AddModeAttr(Decl * D,const AttributeCommonInfo & CI,IdentifierInfo * Name,bool InInstantiation)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
handleNoDebugAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
mergeAlwaysInlineAttr(Decl * D,const AttributeCommonInfo & CI,const IdentifierInfo * Ident)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
mergeInternalLinkageAttr(Decl * D,const ParsedAttr & AL)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 *
mergeInternalLinkageAttr(Decl * D,const InternalLinkageAttr & AL)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
mergeMinSizeAttr(Decl * D,const AttributeCommonInfo & CI)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
mergeOptimizeNoneAttr(Decl * D,const AttributeCommonInfo & CI)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
handleAlwaysInlineAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleMinSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleOptimizeNoneAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleConstantAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleSharedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleGlobalAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleDeviceAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleManagedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleGNUInlineAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleCallConvAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleSuppressAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleLifetimeCategoryAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleRandomizeLayoutAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNoRandomizeLayoutAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
CheckCallingConvAttr(const ParsedAttr & Attrs,CallingConv & CC,const FunctionDecl * FD,CUDAFunctionTarget CFT)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
CheckRegparmAttr(const ParsedAttr & AL,unsigned & numParams)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.
getOffloadArch(const TargetInfo & TI)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.
makeLaunchBoundsArgExpr(Sema & S,Expr * E,const CUDALaunchBoundsAttr & AL,const unsigned Idx)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 *
CreateLaunchBoundsAttr(const AttributeCommonInfo & CI,Expr * MaxThreads,Expr * MinBlocks,Expr * MaxBlocks)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
AddLaunchBoundsAttr(Decl * D,const AttributeCommonInfo & CI,Expr * MaxThreads,Expr * MinBlocks,Expr * MaxBlocks)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
handleLaunchBoundsAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleArgumentWithTypeTagAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleTypeTagForDatatypeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleXRayLogArgsAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handlePatchableFunctionEntryAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleBuiltinAliasAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNullableTypeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handlePreferredTypeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
mergeUuidAttr(Decl * D,const AttributeCommonInfo & CI,StringRef UuidAsWritten,MSGuidDecl * GuidDecl)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
handleUuidAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleMSInheritanceAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleDeclspecThreadAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleMSConstexprAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAbiTagAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
hasBTFDeclTagAttr(Decl * D,StringRef Tag)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
handleBTFDeclTagAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
mergeBTFDeclTagAttr(Decl * D,const BTFDeclTagAttr & AL)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
handleInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleLayoutVersion(Sema & S,Decl * D,const ParsedAttr & AL)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
mergeDLLImportAttr(Decl * D,const AttributeCommonInfo & CI)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
mergeDLLExportAttr(Decl * D,const AttributeCommonInfo & CI)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
handleDLLAttr(Sema & S,Decl * D,const ParsedAttr & A)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 *
mergeMSInheritanceAttr(Decl * D,const AttributeCommonInfo & CI,bool BestCase,MSInheritanceModel Model)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
handleCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAssertCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAcquireCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleTryAcquireCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleReleaseCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleRequiresCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleDeprecatedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
isGlobalVar(const Decl * D)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
isSanitizerAttributeAllowedOnGlobals(StringRef Sanitizer)576681ad6265SDimitry Andric static bool isSanitizerAttributeAllowedOnGlobals(StringRef Sanitizer) {
576781ad6265SDimitry Andric return Sanitizer == "address" || Sanitizer == "hwaddress" ||
576881ad6265SDimitry Andric Sanitizer == "memtag";
576981ad6265SDimitry Andric }
577081ad6265SDimitry Andric
handleNoSanitizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNoSanitizeSpecificAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleInternalLinkageAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleZeroCallUsedRegsAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleCountedByAttrField(Sema & S,Decl * D,const ParsedAttr & AL)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
handleFunctionReturnThunksAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAvailableOnlyInDefaultEvalMethod(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNoMergeAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleNoUniqueAddressAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleDestroyAttr(Sema & S,Decl * D,const ParsedAttr & A)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
handleUninitializedAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleMIGServerRoutineAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleMSAllocatorAttr(Sema & S,Decl * D,const ParsedAttr & AL)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
handleAcquireHandleAttr(Sema & S,Decl * D,const ParsedAttr & AL)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>
handleHandleAttr(Sema & S,Decl * D,const ParsedAttr & AL)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>
handleUnsafeBufferUsage(Sema & S,Decl * D,const ParsedAttr & AL)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
handleCFGuardAttr(Sema & S,Decl * D,const ParsedAttr & AL)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>
findEnforceTCBAttrByName(Decl * D,StringRef Name)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>
handleEnforceTCBAttr(Sema & S,Decl * D,const ParsedAttr & AL)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>
mergeEnforceTCBAttrImpl(Sema & S,Decl * D,const AttrTy & AL)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
mergeEnforceTCBAttr(Decl * D,const EnforceTCBAttr & AL)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
mergeEnforceTCBLeafAttr(Decl * D,const EnforceTCBLeafAttr & AL)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
handleVTablePointerAuthentication(Sema & S,Decl * D,const ParsedAttr & AL)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.
MustDelayAttributeArguments(const ParsedAttr & AL)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
ProcessDeclAttribute(Sema & S,Scope * scope,Decl * D,const ParsedAttr & AL,const Sema::ProcessDeclAttributeOptions & Options)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
ProcessDeclAttributeList(Scope * S,Decl * D,const ParsedAttributesView & AttrList,const ProcessDeclAttributeOptions & Options)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
ProcessDeclAttributeDelayed(Decl * D,const ParsedAttributesView & AttrList)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
ProcessAccessDeclAttributeList(AccessSpecDecl * ASDecl,const ParsedAttributesView & AttrList)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.
checkUnusedDeclAttributes(Sema & S,const ParsedAttributesView & A)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
checkUnusedDeclAttributes(Declarator & D)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
DeclClonePragmaWeak(NamedDecl * ND,const IdentifierInfo * II,SourceLocation Loc)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
DeclApplyPragmaWeak(Scope * S,NamedDecl * ND,const WeakInfo & W)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
ProcessPragmaWeak(Scope * S,Decl * D)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.
ProcessDeclAttributes(Scope * S,Decl * D,const Declarator & PD)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.
isForbiddenTypeAllowed(Sema & S,Decl * D,const DelayedDiagnostic & diag,UnavailableAttr::ImplicitReason & reason)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.
handleDelayedForbiddenType(Sema & S,DelayedDiagnostic & DD,Decl * D)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
PopParsingDeclaration(ParsingDeclState state,Decl * decl)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
redelayDiagnostics(DelayedDiagnosticPool & pool)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