xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Sema/SemaDeclAttr.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg //  This file implements decl-related attribute processing.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/AST/ASTConsumer.h"
147330f729Sjoerg #include "clang/AST/ASTContext.h"
157330f729Sjoerg #include "clang/AST/ASTMutationListener.h"
167330f729Sjoerg #include "clang/AST/CXXInheritance.h"
177330f729Sjoerg #include "clang/AST/DeclCXX.h"
187330f729Sjoerg #include "clang/AST/DeclObjC.h"
197330f729Sjoerg #include "clang/AST/DeclTemplate.h"
207330f729Sjoerg #include "clang/AST/Expr.h"
217330f729Sjoerg #include "clang/AST/ExprCXX.h"
227330f729Sjoerg #include "clang/AST/Mangle.h"
237330f729Sjoerg #include "clang/AST/RecursiveASTVisitor.h"
24*e038c9c4Sjoerg #include "clang/AST/Type.h"
257330f729Sjoerg #include "clang/Basic/CharInfo.h"
26*e038c9c4Sjoerg #include "clang/Basic/SourceLocation.h"
277330f729Sjoerg #include "clang/Basic/SourceManager.h"
287330f729Sjoerg #include "clang/Basic/TargetBuiltins.h"
297330f729Sjoerg #include "clang/Basic/TargetInfo.h"
307330f729Sjoerg #include "clang/Lex/Preprocessor.h"
317330f729Sjoerg #include "clang/Sema/DeclSpec.h"
327330f729Sjoerg #include "clang/Sema/DelayedDiagnostic.h"
337330f729Sjoerg #include "clang/Sema/Initialization.h"
347330f729Sjoerg #include "clang/Sema/Lookup.h"
35*e038c9c4Sjoerg #include "clang/Sema/ParsedAttr.h"
367330f729Sjoerg #include "clang/Sema/Scope.h"
377330f729Sjoerg #include "clang/Sema/ScopeInfo.h"
387330f729Sjoerg #include "clang/Sema/SemaInternal.h"
39*e038c9c4Sjoerg #include "llvm/ADT/Optional.h"
407330f729Sjoerg #include "llvm/ADT/STLExtras.h"
417330f729Sjoerg #include "llvm/ADT/StringExtras.h"
42*e038c9c4Sjoerg #include "llvm/IR/Assumptions.h"
43*e038c9c4Sjoerg #include "llvm/MC/MCSectionMachO.h"
44*e038c9c4Sjoerg #include "llvm/Support/Error.h"
457330f729Sjoerg #include "llvm/Support/MathExtras.h"
46*e038c9c4Sjoerg #include "llvm/Support/raw_ostream.h"
477330f729Sjoerg 
487330f729Sjoerg using namespace clang;
497330f729Sjoerg using namespace sema;
507330f729Sjoerg 
517330f729Sjoerg namespace AttributeLangSupport {
527330f729Sjoerg   enum LANG {
537330f729Sjoerg     C,
547330f729Sjoerg     Cpp,
557330f729Sjoerg     ObjC
567330f729Sjoerg   };
577330f729Sjoerg } // end namespace AttributeLangSupport
587330f729Sjoerg 
597330f729Sjoerg //===----------------------------------------------------------------------===//
607330f729Sjoerg //  Helper functions
617330f729Sjoerg //===----------------------------------------------------------------------===//
627330f729Sjoerg 
637330f729Sjoerg /// isFunctionOrMethod - Return true if the given decl has function
647330f729Sjoerg /// type (function or function-typed variable) or an Objective-C
657330f729Sjoerg /// method.
isFunctionOrMethod(const Decl * D)667330f729Sjoerg static bool isFunctionOrMethod(const Decl *D) {
677330f729Sjoerg   return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
687330f729Sjoerg }
697330f729Sjoerg 
707330f729Sjoerg /// Return true if the given decl has function type (function or
717330f729Sjoerg /// function-typed variable) or an Objective-C method or a block.
isFunctionOrMethodOrBlock(const Decl * D)727330f729Sjoerg static bool isFunctionOrMethodOrBlock(const Decl *D) {
737330f729Sjoerg   return isFunctionOrMethod(D) || isa<BlockDecl>(D);
747330f729Sjoerg }
757330f729Sjoerg 
767330f729Sjoerg /// Return true if the given decl has a declarator that should have
777330f729Sjoerg /// been processed by Sema::GetTypeForDeclarator.
hasDeclarator(const Decl * D)787330f729Sjoerg static bool hasDeclarator(const Decl *D) {
797330f729Sjoerg   // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
807330f729Sjoerg   return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) ||
817330f729Sjoerg          isa<ObjCPropertyDecl>(D);
827330f729Sjoerg }
837330f729Sjoerg 
847330f729Sjoerg /// hasFunctionProto - Return true if the given decl has a argument
857330f729Sjoerg /// information. This decl should have already passed
867330f729Sjoerg /// isFunctionOrMethod or isFunctionOrMethodOrBlock.
hasFunctionProto(const Decl * D)877330f729Sjoerg static bool hasFunctionProto(const Decl *D) {
887330f729Sjoerg   if (const FunctionType *FnTy = D->getFunctionType())
897330f729Sjoerg     return isa<FunctionProtoType>(FnTy);
907330f729Sjoerg   return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
917330f729Sjoerg }
927330f729Sjoerg 
937330f729Sjoerg /// getFunctionOrMethodNumParams - Return number of function or method
947330f729Sjoerg /// parameters. It is an error to call this on a K&R function (use
957330f729Sjoerg /// hasFunctionProto first).
getFunctionOrMethodNumParams(const Decl * D)967330f729Sjoerg static unsigned getFunctionOrMethodNumParams(const Decl *D) {
977330f729Sjoerg   if (const FunctionType *FnTy = D->getFunctionType())
987330f729Sjoerg     return cast<FunctionProtoType>(FnTy)->getNumParams();
997330f729Sjoerg   if (const auto *BD = dyn_cast<BlockDecl>(D))
1007330f729Sjoerg     return BD->getNumParams();
1017330f729Sjoerg   return cast<ObjCMethodDecl>(D)->param_size();
1027330f729Sjoerg }
1037330f729Sjoerg 
getFunctionOrMethodParam(const Decl * D,unsigned Idx)1047330f729Sjoerg static const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
1057330f729Sjoerg                                                    unsigned Idx) {
1067330f729Sjoerg   if (const auto *FD = dyn_cast<FunctionDecl>(D))
1077330f729Sjoerg     return FD->getParamDecl(Idx);
1087330f729Sjoerg   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
1097330f729Sjoerg     return MD->getParamDecl(Idx);
1107330f729Sjoerg   if (const auto *BD = dyn_cast<BlockDecl>(D))
1117330f729Sjoerg     return BD->getParamDecl(Idx);
1127330f729Sjoerg   return nullptr;
1137330f729Sjoerg }
1147330f729Sjoerg 
getFunctionOrMethodParamType(const Decl * D,unsigned Idx)1157330f729Sjoerg static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
1167330f729Sjoerg   if (const FunctionType *FnTy = D->getFunctionType())
1177330f729Sjoerg     return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
1187330f729Sjoerg   if (const auto *BD = dyn_cast<BlockDecl>(D))
1197330f729Sjoerg     return BD->getParamDecl(Idx)->getType();
1207330f729Sjoerg 
1217330f729Sjoerg   return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
1227330f729Sjoerg }
1237330f729Sjoerg 
getFunctionOrMethodParamRange(const Decl * D,unsigned Idx)1247330f729Sjoerg static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
1257330f729Sjoerg   if (auto *PVD = getFunctionOrMethodParam(D, Idx))
1267330f729Sjoerg     return PVD->getSourceRange();
1277330f729Sjoerg   return SourceRange();
1287330f729Sjoerg }
1297330f729Sjoerg 
getFunctionOrMethodResultType(const Decl * D)1307330f729Sjoerg static QualType getFunctionOrMethodResultType(const Decl *D) {
1317330f729Sjoerg   if (const FunctionType *FnTy = D->getFunctionType())
1327330f729Sjoerg     return FnTy->getReturnType();
1337330f729Sjoerg   return cast<ObjCMethodDecl>(D)->getReturnType();
1347330f729Sjoerg }
1357330f729Sjoerg 
getFunctionOrMethodResultSourceRange(const Decl * D)1367330f729Sjoerg static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
1377330f729Sjoerg   if (const auto *FD = dyn_cast<FunctionDecl>(D))
1387330f729Sjoerg     return FD->getReturnTypeSourceRange();
1397330f729Sjoerg   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
1407330f729Sjoerg     return MD->getReturnTypeSourceRange();
1417330f729Sjoerg   return SourceRange();
1427330f729Sjoerg }
1437330f729Sjoerg 
isFunctionOrMethodVariadic(const Decl * D)1447330f729Sjoerg static bool isFunctionOrMethodVariadic(const Decl *D) {
1457330f729Sjoerg   if (const FunctionType *FnTy = D->getFunctionType())
1467330f729Sjoerg     return cast<FunctionProtoType>(FnTy)->isVariadic();
1477330f729Sjoerg   if (const auto *BD = dyn_cast<BlockDecl>(D))
1487330f729Sjoerg     return BD->isVariadic();
1497330f729Sjoerg   return cast<ObjCMethodDecl>(D)->isVariadic();
1507330f729Sjoerg }
1517330f729Sjoerg 
isInstanceMethod(const Decl * D)1527330f729Sjoerg static bool isInstanceMethod(const Decl *D) {
1537330f729Sjoerg   if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
1547330f729Sjoerg     return MethodDecl->isInstance();
1557330f729Sjoerg   return false;
1567330f729Sjoerg }
1577330f729Sjoerg 
isNSStringType(QualType T,ASTContext & Ctx,bool AllowNSAttributedString=false)158*e038c9c4Sjoerg static inline bool isNSStringType(QualType T, ASTContext &Ctx,
159*e038c9c4Sjoerg                                   bool AllowNSAttributedString = false) {
1607330f729Sjoerg   const auto *PT = T->getAs<ObjCObjectPointerType>();
1617330f729Sjoerg   if (!PT)
1627330f729Sjoerg     return false;
1637330f729Sjoerg 
1647330f729Sjoerg   ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
1657330f729Sjoerg   if (!Cls)
1667330f729Sjoerg     return false;
1677330f729Sjoerg 
1687330f729Sjoerg   IdentifierInfo* ClsName = Cls->getIdentifier();
1697330f729Sjoerg 
170*e038c9c4Sjoerg   if (AllowNSAttributedString &&
171*e038c9c4Sjoerg       ClsName == &Ctx.Idents.get("NSAttributedString"))
172*e038c9c4Sjoerg     return true;
1737330f729Sjoerg   // FIXME: Should we walk the chain of classes?
1747330f729Sjoerg   return ClsName == &Ctx.Idents.get("NSString") ||
1757330f729Sjoerg          ClsName == &Ctx.Idents.get("NSMutableString");
1767330f729Sjoerg }
1777330f729Sjoerg 
isCFStringType(QualType T,ASTContext & Ctx)1787330f729Sjoerg static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
1797330f729Sjoerg   const auto *PT = T->getAs<PointerType>();
1807330f729Sjoerg   if (!PT)
1817330f729Sjoerg     return false;
1827330f729Sjoerg 
1837330f729Sjoerg   const auto *RT = PT->getPointeeType()->getAs<RecordType>();
1847330f729Sjoerg   if (!RT)
1857330f729Sjoerg     return false;
1867330f729Sjoerg 
1877330f729Sjoerg   const RecordDecl *RD = RT->getDecl();
1887330f729Sjoerg   if (RD->getTagKind() != TTK_Struct)
1897330f729Sjoerg     return false;
1907330f729Sjoerg 
1917330f729Sjoerg   return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
1927330f729Sjoerg }
1937330f729Sjoerg 
getNumAttributeArgs(const ParsedAttr & AL)1947330f729Sjoerg static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
1957330f729Sjoerg   // FIXME: Include the type in the argument list.
1967330f729Sjoerg   return AL.getNumArgs() + AL.hasParsedType();
1977330f729Sjoerg }
1987330f729Sjoerg 
1997330f729Sjoerg /// A helper function to provide Attribute Location for the Attr types
2007330f729Sjoerg /// AND the ParsedAttr.
2017330f729Sjoerg template <typename AttrInfo>
202*e038c9c4Sjoerg static std::enable_if_t<std::is_base_of<Attr, AttrInfo>::value, SourceLocation>
getAttrLoc(const AttrInfo & AL)2037330f729Sjoerg getAttrLoc(const AttrInfo &AL) {
2047330f729Sjoerg   return AL.getLocation();
2057330f729Sjoerg }
getAttrLoc(const ParsedAttr & AL)2067330f729Sjoerg static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); }
2077330f729Sjoerg 
2087330f729Sjoerg /// If Expr is a valid integer constant, get the value of the integer
2097330f729Sjoerg /// expression and return success or failure. May output an error.
2107330f729Sjoerg ///
2117330f729Sjoerg /// Negative argument is implicitly converted to unsigned, unless
2127330f729Sjoerg /// \p StrictlyUnsigned is true.
2137330f729Sjoerg template <typename AttrInfo>
checkUInt32Argument(Sema & S,const AttrInfo & AI,const Expr * Expr,uint32_t & Val,unsigned Idx=UINT_MAX,bool StrictlyUnsigned=false)2147330f729Sjoerg static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
2157330f729Sjoerg                                 uint32_t &Val, unsigned Idx = UINT_MAX,
2167330f729Sjoerg                                 bool StrictlyUnsigned = false) {
217*e038c9c4Sjoerg   Optional<llvm::APSInt> I = llvm::APSInt(32);
2187330f729Sjoerg   if (Expr->isTypeDependent() || Expr->isValueDependent() ||
219*e038c9c4Sjoerg       !(I = Expr->getIntegerConstantExpr(S.Context))) {
2207330f729Sjoerg     if (Idx != UINT_MAX)
2217330f729Sjoerg       S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
2227330f729Sjoerg           << &AI << Idx << AANT_ArgumentIntegerConstant
2237330f729Sjoerg           << Expr->getSourceRange();
2247330f729Sjoerg     else
2257330f729Sjoerg       S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type)
2267330f729Sjoerg           << &AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange();
2277330f729Sjoerg     return false;
2287330f729Sjoerg   }
2297330f729Sjoerg 
230*e038c9c4Sjoerg   if (!I->isIntN(32)) {
2317330f729Sjoerg     S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
232*e038c9c4Sjoerg         << I->toString(10, false) << 32 << /* Unsigned */ 1;
2337330f729Sjoerg     return false;
2347330f729Sjoerg   }
2357330f729Sjoerg 
236*e038c9c4Sjoerg   if (StrictlyUnsigned && I->isSigned() && I->isNegative()) {
2377330f729Sjoerg     S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer)
2387330f729Sjoerg         << &AI << /*non-negative*/ 1;
2397330f729Sjoerg     return false;
2407330f729Sjoerg   }
2417330f729Sjoerg 
242*e038c9c4Sjoerg   Val = (uint32_t)I->getZExtValue();
2437330f729Sjoerg   return true;
2447330f729Sjoerg }
2457330f729Sjoerg 
2467330f729Sjoerg /// Wrapper around checkUInt32Argument, with an extra check to be sure
2477330f729Sjoerg /// that the result will fit into a regular (signed) int. All args have the same
2487330f729Sjoerg /// purpose as they do in checkUInt32Argument.
2497330f729Sjoerg template <typename AttrInfo>
checkPositiveIntArgument(Sema & S,const AttrInfo & AI,const Expr * Expr,int & Val,unsigned Idx=UINT_MAX)2507330f729Sjoerg static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr,
2517330f729Sjoerg                                      int &Val, unsigned Idx = UINT_MAX) {
2527330f729Sjoerg   uint32_t UVal;
2537330f729Sjoerg   if (!checkUInt32Argument(S, AI, Expr, UVal, Idx))
2547330f729Sjoerg     return false;
2557330f729Sjoerg 
2567330f729Sjoerg   if (UVal > (uint32_t)std::numeric_limits<int>::max()) {
2577330f729Sjoerg     llvm::APSInt I(32); // for toString
2587330f729Sjoerg     I = UVal;
2597330f729Sjoerg     S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
2607330f729Sjoerg         << I.toString(10, false) << 32 << /* Unsigned */ 0;
2617330f729Sjoerg     return false;
2627330f729Sjoerg   }
2637330f729Sjoerg 
2647330f729Sjoerg   Val = UVal;
2657330f729Sjoerg   return true;
2667330f729Sjoerg }
2677330f729Sjoerg 
2687330f729Sjoerg /// Diagnose mutually exclusive attributes when present on a given
2697330f729Sjoerg /// declaration. Returns true if diagnosed.
2707330f729Sjoerg template <typename AttrTy>
checkAttrMutualExclusion(Sema & S,Decl * D,const ParsedAttr & AL)2717330f729Sjoerg static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) {
2727330f729Sjoerg   if (const auto *A = D->getAttr<AttrTy>()) {
2737330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A;
2747330f729Sjoerg     S.Diag(A->getLocation(), diag::note_conflicting_attribute);
2757330f729Sjoerg     return true;
2767330f729Sjoerg   }
2777330f729Sjoerg   return false;
2787330f729Sjoerg }
2797330f729Sjoerg 
2807330f729Sjoerg template <typename AttrTy>
checkAttrMutualExclusion(Sema & S,Decl * D,const Attr & AL)2817330f729Sjoerg static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) {
2827330f729Sjoerg   if (const auto *A = D->getAttr<AttrTy>()) {
2837330f729Sjoerg     S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL
2847330f729Sjoerg                                                                       << A;
2857330f729Sjoerg     S.Diag(A->getLocation(), diag::note_conflicting_attribute);
2867330f729Sjoerg     return true;
2877330f729Sjoerg   }
2887330f729Sjoerg   return false;
2897330f729Sjoerg }
2907330f729Sjoerg 
2917330f729Sjoerg /// Check if IdxExpr is a valid parameter index for a function or
2927330f729Sjoerg /// instance method D.  May output an error.
2937330f729Sjoerg ///
2947330f729Sjoerg /// \returns true if IdxExpr is a valid index.
2957330f729Sjoerg template <typename AttrInfo>
checkFunctionOrMethodParameterIndex(Sema & S,const Decl * D,const AttrInfo & AI,unsigned AttrArgNum,const Expr * IdxExpr,ParamIdx & Idx,bool CanIndexImplicitThis=false)2967330f729Sjoerg static bool checkFunctionOrMethodParameterIndex(
2977330f729Sjoerg     Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum,
2987330f729Sjoerg     const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false) {
2997330f729Sjoerg   assert(isFunctionOrMethodOrBlock(D));
3007330f729Sjoerg 
3017330f729Sjoerg   // In C++ the implicit 'this' function parameter also counts.
3027330f729Sjoerg   // Parameters are counted from one.
3037330f729Sjoerg   bool HP = hasFunctionProto(D);
3047330f729Sjoerg   bool HasImplicitThisParam = isInstanceMethod(D);
3057330f729Sjoerg   bool IV = HP && isFunctionOrMethodVariadic(D);
3067330f729Sjoerg   unsigned NumParams =
3077330f729Sjoerg       (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
3087330f729Sjoerg 
309*e038c9c4Sjoerg   Optional<llvm::APSInt> IdxInt;
3107330f729Sjoerg   if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
311*e038c9c4Sjoerg       !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) {
3127330f729Sjoerg     S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
3137330f729Sjoerg         << &AI << AttrArgNum << AANT_ArgumentIntegerConstant
3147330f729Sjoerg         << IdxExpr->getSourceRange();
3157330f729Sjoerg     return false;
3167330f729Sjoerg   }
3177330f729Sjoerg 
318*e038c9c4Sjoerg   unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
3197330f729Sjoerg   if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
3207330f729Sjoerg     S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
3217330f729Sjoerg         << &AI << AttrArgNum << IdxExpr->getSourceRange();
3227330f729Sjoerg     return false;
3237330f729Sjoerg   }
3247330f729Sjoerg   if (HasImplicitThisParam && !CanIndexImplicitThis) {
3257330f729Sjoerg     if (IdxSource == 1) {
3267330f729Sjoerg       S.Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
3277330f729Sjoerg           << &AI << IdxExpr->getSourceRange();
3287330f729Sjoerg       return false;
3297330f729Sjoerg     }
3307330f729Sjoerg   }
3317330f729Sjoerg 
3327330f729Sjoerg   Idx = ParamIdx(IdxSource, D);
3337330f729Sjoerg   return true;
3347330f729Sjoerg }
3357330f729Sjoerg 
3367330f729Sjoerg /// Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
3377330f729Sjoerg /// If not emit an error and return false. If the argument is an identifier it
3387330f729Sjoerg /// will emit an error with a fixit hint and treat it as if it was a string
3397330f729Sjoerg /// literal.
checkStringLiteralArgumentAttr(const ParsedAttr & AL,unsigned ArgNum,StringRef & Str,SourceLocation * ArgLocation)3407330f729Sjoerg bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum,
3417330f729Sjoerg                                           StringRef &Str,
3427330f729Sjoerg                                           SourceLocation *ArgLocation) {
3437330f729Sjoerg   // Look for identifiers. If we have one emit a hint to fix it to a literal.
3447330f729Sjoerg   if (AL.isArgIdent(ArgNum)) {
3457330f729Sjoerg     IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum);
3467330f729Sjoerg     Diag(Loc->Loc, diag::err_attribute_argument_type)
3477330f729Sjoerg         << AL << AANT_ArgumentString
3487330f729Sjoerg         << FixItHint::CreateInsertion(Loc->Loc, "\"")
3497330f729Sjoerg         << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\"");
3507330f729Sjoerg     Str = Loc->Ident->getName();
3517330f729Sjoerg     if (ArgLocation)
3527330f729Sjoerg       *ArgLocation = Loc->Loc;
3537330f729Sjoerg     return true;
3547330f729Sjoerg   }
3557330f729Sjoerg 
3567330f729Sjoerg   // Now check for an actual string literal.
3577330f729Sjoerg   Expr *ArgExpr = AL.getArgAsExpr(ArgNum);
3587330f729Sjoerg   const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
3597330f729Sjoerg   if (ArgLocation)
3607330f729Sjoerg     *ArgLocation = ArgExpr->getBeginLoc();
3617330f729Sjoerg 
3627330f729Sjoerg   if (!Literal || !Literal->isAscii()) {
3637330f729Sjoerg     Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type)
3647330f729Sjoerg         << AL << AANT_ArgumentString;
3657330f729Sjoerg     return false;
3667330f729Sjoerg   }
3677330f729Sjoerg 
3687330f729Sjoerg   Str = Literal->getString();
3697330f729Sjoerg   return true;
3707330f729Sjoerg }
3717330f729Sjoerg 
3727330f729Sjoerg /// Applies the given attribute to the Decl without performing any
3737330f729Sjoerg /// additional semantic checking.
3747330f729Sjoerg template <typename AttrType>
handleSimpleAttribute(Sema & S,Decl * D,const AttributeCommonInfo & CI)3757330f729Sjoerg static void handleSimpleAttribute(Sema &S, Decl *D,
3767330f729Sjoerg                                   const AttributeCommonInfo &CI) {
3777330f729Sjoerg   D->addAttr(::new (S.Context) AttrType(S.Context, CI));
3787330f729Sjoerg }
3797330f729Sjoerg 
3807330f729Sjoerg template <typename... DiagnosticArgs>
3817330f729Sjoerg static const Sema::SemaDiagnosticBuilder&
appendDiagnostics(const Sema::SemaDiagnosticBuilder & Bldr)3827330f729Sjoerg appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) {
3837330f729Sjoerg   return Bldr;
3847330f729Sjoerg }
3857330f729Sjoerg 
3867330f729Sjoerg template <typename T, typename... DiagnosticArgs>
3877330f729Sjoerg static const Sema::SemaDiagnosticBuilder&
appendDiagnostics(const Sema::SemaDiagnosticBuilder & Bldr,T && ExtraArg,DiagnosticArgs &&...ExtraArgs)3887330f729Sjoerg appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
3897330f729Sjoerg                   DiagnosticArgs &&... ExtraArgs) {
3907330f729Sjoerg   return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
3917330f729Sjoerg                            std::forward<DiagnosticArgs>(ExtraArgs)...);
3927330f729Sjoerg }
3937330f729Sjoerg 
394*e038c9c4Sjoerg /// Add an attribute @c AttrType to declaration @c D, provided that
395*e038c9c4Sjoerg /// @c PassesCheck is true.
396*e038c9c4Sjoerg /// Otherwise, emit diagnostic @c DiagID, passing in all parameters
397*e038c9c4Sjoerg /// specified in @c ExtraArgs.
3987330f729Sjoerg template <typename AttrType, typename... DiagnosticArgs>
handleSimpleAttributeOrDiagnose(Sema & S,Decl * D,const AttributeCommonInfo & CI,bool PassesCheck,unsigned DiagID,DiagnosticArgs &&...ExtraArgs)3997330f729Sjoerg static void handleSimpleAttributeOrDiagnose(Sema &S, Decl *D,
4007330f729Sjoerg                                             const AttributeCommonInfo &CI,
4017330f729Sjoerg                                             bool PassesCheck, unsigned DiagID,
4027330f729Sjoerg                                             DiagnosticArgs &&... ExtraArgs) {
4037330f729Sjoerg   if (!PassesCheck) {
4047330f729Sjoerg     Sema::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID);
4057330f729Sjoerg     appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
4067330f729Sjoerg     return;
4077330f729Sjoerg   }
4087330f729Sjoerg   handleSimpleAttribute<AttrType>(S, D, CI);
4097330f729Sjoerg }
4107330f729Sjoerg 
4117330f729Sjoerg /// Check if the passed-in expression is of type int or bool.
isIntOrBool(Expr * Exp)4127330f729Sjoerg static bool isIntOrBool(Expr *Exp) {
4137330f729Sjoerg   QualType QT = Exp->getType();
4147330f729Sjoerg   return QT->isBooleanType() || QT->isIntegerType();
4157330f729Sjoerg }
4167330f729Sjoerg 
4177330f729Sjoerg 
4187330f729Sjoerg // Check to see if the type is a smart pointer of some kind.  We assume
4197330f729Sjoerg // it's a smart pointer if it defines both operator-> and operator*.
threadSafetyCheckIsSmartPointer(Sema & S,const RecordType * RT)4207330f729Sjoerg static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
4217330f729Sjoerg   auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record,
4227330f729Sjoerg                                           OverloadedOperatorKind Op) {
4237330f729Sjoerg     DeclContextLookupResult Result =
4247330f729Sjoerg         Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op));
4257330f729Sjoerg     return !Result.empty();
4267330f729Sjoerg   };
4277330f729Sjoerg 
4287330f729Sjoerg   const RecordDecl *Record = RT->getDecl();
4297330f729Sjoerg   bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star);
4307330f729Sjoerg   bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow);
4317330f729Sjoerg   if (foundStarOperator && foundArrowOperator)
4327330f729Sjoerg     return true;
4337330f729Sjoerg 
4347330f729Sjoerg   const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record);
4357330f729Sjoerg   if (!CXXRecord)
4367330f729Sjoerg     return false;
4377330f729Sjoerg 
4387330f729Sjoerg   for (auto BaseSpecifier : CXXRecord->bases()) {
4397330f729Sjoerg     if (!foundStarOperator)
4407330f729Sjoerg       foundStarOperator = IsOverloadedOperatorPresent(
4417330f729Sjoerg           BaseSpecifier.getType()->getAsRecordDecl(), OO_Star);
4427330f729Sjoerg     if (!foundArrowOperator)
4437330f729Sjoerg       foundArrowOperator = IsOverloadedOperatorPresent(
4447330f729Sjoerg           BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow);
4457330f729Sjoerg   }
4467330f729Sjoerg 
4477330f729Sjoerg   if (foundStarOperator && foundArrowOperator)
4487330f729Sjoerg     return true;
4497330f729Sjoerg 
4507330f729Sjoerg   return false;
4517330f729Sjoerg }
4527330f729Sjoerg 
4537330f729Sjoerg /// Check if passed in Decl is a pointer type.
4547330f729Sjoerg /// Note that this function may produce an error message.
4557330f729Sjoerg /// \return true if the Decl is a pointer type; false otherwise
threadSafetyCheckIsPointer(Sema & S,const Decl * D,const ParsedAttr & AL)4567330f729Sjoerg static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
4577330f729Sjoerg                                        const ParsedAttr &AL) {
4587330f729Sjoerg   const auto *VD = cast<ValueDecl>(D);
4597330f729Sjoerg   QualType QT = VD->getType();
4607330f729Sjoerg   if (QT->isAnyPointerType())
4617330f729Sjoerg     return true;
4627330f729Sjoerg 
4637330f729Sjoerg   if (const auto *RT = QT->getAs<RecordType>()) {
4647330f729Sjoerg     // If it's an incomplete type, it could be a smart pointer; skip it.
4657330f729Sjoerg     // (We don't want to force template instantiation if we can avoid it,
4667330f729Sjoerg     // since that would alter the order in which templates are instantiated.)
4677330f729Sjoerg     if (RT->isIncompleteType())
4687330f729Sjoerg       return true;
4697330f729Sjoerg 
4707330f729Sjoerg     if (threadSafetyCheckIsSmartPointer(S, RT))
4717330f729Sjoerg       return true;
4727330f729Sjoerg   }
4737330f729Sjoerg 
4747330f729Sjoerg   S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << AL << QT;
4757330f729Sjoerg   return false;
4767330f729Sjoerg }
4777330f729Sjoerg 
4787330f729Sjoerg /// Checks that the passed in QualType either is of RecordType or points
4797330f729Sjoerg /// to RecordType. Returns the relevant RecordType, null if it does not exit.
getRecordType(QualType QT)4807330f729Sjoerg static const RecordType *getRecordType(QualType QT) {
4817330f729Sjoerg   if (const auto *RT = QT->getAs<RecordType>())
4827330f729Sjoerg     return RT;
4837330f729Sjoerg 
4847330f729Sjoerg   // Now check if we point to record type.
4857330f729Sjoerg   if (const auto *PT = QT->getAs<PointerType>())
4867330f729Sjoerg     return PT->getPointeeType()->getAs<RecordType>();
4877330f729Sjoerg 
4887330f729Sjoerg   return nullptr;
4897330f729Sjoerg }
4907330f729Sjoerg 
4917330f729Sjoerg template <typename AttrType>
checkRecordDeclForAttr(const RecordDecl * RD)4927330f729Sjoerg static bool checkRecordDeclForAttr(const RecordDecl *RD) {
4937330f729Sjoerg   // Check if the record itself has the attribute.
4947330f729Sjoerg   if (RD->hasAttr<AttrType>())
4957330f729Sjoerg     return true;
4967330f729Sjoerg 
4977330f729Sjoerg   // Else check if any base classes have the attribute.
4987330f729Sjoerg   if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
499*e038c9c4Sjoerg     if (!CRD->forallBases([](const CXXRecordDecl *Base) {
500*e038c9c4Sjoerg           return !Base->hasAttr<AttrType>();
501*e038c9c4Sjoerg         }))
5027330f729Sjoerg       return true;
5037330f729Sjoerg   }
5047330f729Sjoerg   return false;
5057330f729Sjoerg }
5067330f729Sjoerg 
checkRecordTypeForCapability(Sema & S,QualType Ty)5077330f729Sjoerg static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
5087330f729Sjoerg   const RecordType *RT = getRecordType(Ty);
5097330f729Sjoerg 
5107330f729Sjoerg   if (!RT)
5117330f729Sjoerg     return false;
5127330f729Sjoerg 
5137330f729Sjoerg   // Don't check for the capability if the class hasn't been defined yet.
5147330f729Sjoerg   if (RT->isIncompleteType())
5157330f729Sjoerg     return true;
5167330f729Sjoerg 
5177330f729Sjoerg   // Allow smart pointers to be used as capability objects.
5187330f729Sjoerg   // FIXME -- Check the type that the smart pointer points to.
5197330f729Sjoerg   if (threadSafetyCheckIsSmartPointer(S, RT))
5207330f729Sjoerg     return true;
5217330f729Sjoerg 
5227330f729Sjoerg   return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl());
5237330f729Sjoerg }
5247330f729Sjoerg 
checkTypedefTypeForCapability(QualType Ty)5257330f729Sjoerg static bool checkTypedefTypeForCapability(QualType Ty) {
5267330f729Sjoerg   const auto *TD = Ty->getAs<TypedefType>();
5277330f729Sjoerg   if (!TD)
5287330f729Sjoerg     return false;
5297330f729Sjoerg 
5307330f729Sjoerg   TypedefNameDecl *TN = TD->getDecl();
5317330f729Sjoerg   if (!TN)
5327330f729Sjoerg     return false;
5337330f729Sjoerg 
5347330f729Sjoerg   return TN->hasAttr<CapabilityAttr>();
5357330f729Sjoerg }
5367330f729Sjoerg 
typeHasCapability(Sema & S,QualType Ty)5377330f729Sjoerg static bool typeHasCapability(Sema &S, QualType Ty) {
5387330f729Sjoerg   if (checkTypedefTypeForCapability(Ty))
5397330f729Sjoerg     return true;
5407330f729Sjoerg 
5417330f729Sjoerg   if (checkRecordTypeForCapability(S, Ty))
5427330f729Sjoerg     return true;
5437330f729Sjoerg 
5447330f729Sjoerg   return false;
5457330f729Sjoerg }
5467330f729Sjoerg 
isCapabilityExpr(Sema & S,const Expr * Ex)5477330f729Sjoerg static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
5487330f729Sjoerg   // Capability expressions are simple expressions involving the boolean logic
5497330f729Sjoerg   // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once
5507330f729Sjoerg   // a DeclRefExpr is found, its type should be checked to determine whether it
5517330f729Sjoerg   // is a capability or not.
5527330f729Sjoerg 
5537330f729Sjoerg   if (const auto *E = dyn_cast<CastExpr>(Ex))
5547330f729Sjoerg     return isCapabilityExpr(S, E->getSubExpr());
5557330f729Sjoerg   else if (const auto *E = dyn_cast<ParenExpr>(Ex))
5567330f729Sjoerg     return isCapabilityExpr(S, E->getSubExpr());
5577330f729Sjoerg   else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) {
5587330f729Sjoerg     if (E->getOpcode() == UO_LNot || E->getOpcode() == UO_AddrOf ||
5597330f729Sjoerg         E->getOpcode() == UO_Deref)
5607330f729Sjoerg       return isCapabilityExpr(S, E->getSubExpr());
5617330f729Sjoerg     return false;
5627330f729Sjoerg   } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) {
5637330f729Sjoerg     if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr)
5647330f729Sjoerg       return isCapabilityExpr(S, E->getLHS()) &&
5657330f729Sjoerg              isCapabilityExpr(S, E->getRHS());
5667330f729Sjoerg     return false;
5677330f729Sjoerg   }
5687330f729Sjoerg 
5697330f729Sjoerg   return typeHasCapability(S, Ex->getType());
5707330f729Sjoerg }
5717330f729Sjoerg 
5727330f729Sjoerg /// Checks that all attribute arguments, starting from Sidx, resolve to
5737330f729Sjoerg /// a capability object.
5747330f729Sjoerg /// \param Sidx The attribute argument index to start checking with.
5757330f729Sjoerg /// \param ParamIdxOk Whether an argument can be indexing into a function
5767330f729Sjoerg /// parameter list.
checkAttrArgsAreCapabilityObjs(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args,unsigned Sidx=0,bool ParamIdxOk=false)5777330f729Sjoerg static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
5787330f729Sjoerg                                            const ParsedAttr &AL,
5797330f729Sjoerg                                            SmallVectorImpl<Expr *> &Args,
5807330f729Sjoerg                                            unsigned Sidx = 0,
5817330f729Sjoerg                                            bool ParamIdxOk = false) {
5827330f729Sjoerg   if (Sidx == AL.getNumArgs()) {
5837330f729Sjoerg     // If we don't have any capability arguments, the attribute implicitly
5847330f729Sjoerg     // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're
5857330f729Sjoerg     // a non-static method, and that the class is a (scoped) capability.
5867330f729Sjoerg     const auto *MD = dyn_cast<const CXXMethodDecl>(D);
5877330f729Sjoerg     if (MD && !MD->isStatic()) {
5887330f729Sjoerg       const CXXRecordDecl *RD = MD->getParent();
5897330f729Sjoerg       // FIXME -- need to check this again on template instantiation
5907330f729Sjoerg       if (!checkRecordDeclForAttr<CapabilityAttr>(RD) &&
5917330f729Sjoerg           !checkRecordDeclForAttr<ScopedLockableAttr>(RD))
5927330f729Sjoerg         S.Diag(AL.getLoc(),
5937330f729Sjoerg                diag::warn_thread_attribute_not_on_capability_member)
5947330f729Sjoerg             << AL << MD->getParent();
5957330f729Sjoerg     } else {
5967330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member)
5977330f729Sjoerg           << AL;
5987330f729Sjoerg     }
5997330f729Sjoerg   }
6007330f729Sjoerg 
6017330f729Sjoerg   for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) {
6027330f729Sjoerg     Expr *ArgExp = AL.getArgAsExpr(Idx);
6037330f729Sjoerg 
6047330f729Sjoerg     if (ArgExp->isTypeDependent()) {
6057330f729Sjoerg       // FIXME -- need to check this again on template instantiation
6067330f729Sjoerg       Args.push_back(ArgExp);
6077330f729Sjoerg       continue;
6087330f729Sjoerg     }
6097330f729Sjoerg 
6107330f729Sjoerg     if (const auto *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
6117330f729Sjoerg       if (StrLit->getLength() == 0 ||
6127330f729Sjoerg           (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) {
6137330f729Sjoerg         // Pass empty strings to the analyzer without warnings.
6147330f729Sjoerg         // Treat "*" as the universal lock.
6157330f729Sjoerg         Args.push_back(ArgExp);
6167330f729Sjoerg         continue;
6177330f729Sjoerg       }
6187330f729Sjoerg 
6197330f729Sjoerg       // We allow constant strings to be used as a placeholder for expressions
6207330f729Sjoerg       // that are not valid C++ syntax, but warn that they are ignored.
6217330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL;
6227330f729Sjoerg       Args.push_back(ArgExp);
6237330f729Sjoerg       continue;
6247330f729Sjoerg     }
6257330f729Sjoerg 
6267330f729Sjoerg     QualType ArgTy = ArgExp->getType();
6277330f729Sjoerg 
6287330f729Sjoerg     // A pointer to member expression of the form  &MyClass::mu is treated
6297330f729Sjoerg     // specially -- we need to look at the type of the member.
6307330f729Sjoerg     if (const auto *UOp = dyn_cast<UnaryOperator>(ArgExp))
6317330f729Sjoerg       if (UOp->getOpcode() == UO_AddrOf)
6327330f729Sjoerg         if (const auto *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr()))
6337330f729Sjoerg           if (DRE->getDecl()->isCXXInstanceMember())
6347330f729Sjoerg             ArgTy = DRE->getDecl()->getType();
6357330f729Sjoerg 
6367330f729Sjoerg     // First see if we can just cast to record type, or pointer to record type.
6377330f729Sjoerg     const RecordType *RT = getRecordType(ArgTy);
6387330f729Sjoerg 
6397330f729Sjoerg     // Now check if we index into a record type function param.
6407330f729Sjoerg     if(!RT && ParamIdxOk) {
6417330f729Sjoerg       const auto *FD = dyn_cast<FunctionDecl>(D);
6427330f729Sjoerg       const auto *IL = dyn_cast<IntegerLiteral>(ArgExp);
6437330f729Sjoerg       if(FD && IL) {
6447330f729Sjoerg         unsigned int NumParams = FD->getNumParams();
6457330f729Sjoerg         llvm::APInt ArgValue = IL->getValue();
6467330f729Sjoerg         uint64_t ParamIdxFromOne = ArgValue.getZExtValue();
6477330f729Sjoerg         uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;
6487330f729Sjoerg         if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
6497330f729Sjoerg           S.Diag(AL.getLoc(),
6507330f729Sjoerg                  diag::err_attribute_argument_out_of_bounds_extra_info)
6517330f729Sjoerg               << AL << Idx + 1 << NumParams;
6527330f729Sjoerg           continue;
6537330f729Sjoerg         }
6547330f729Sjoerg         ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
6557330f729Sjoerg       }
6567330f729Sjoerg     }
6577330f729Sjoerg 
6587330f729Sjoerg     // If the type does not have a capability, see if the components of the
6597330f729Sjoerg     // expression have capabilities. This allows for writing C code where the
6607330f729Sjoerg     // capability may be on the type, and the expression is a capability
6617330f729Sjoerg     // boolean logic expression. Eg) requires_capability(A || B && !C)
6627330f729Sjoerg     if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp))
6637330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
6647330f729Sjoerg           << AL << ArgTy;
6657330f729Sjoerg 
6667330f729Sjoerg     Args.push_back(ArgExp);
6677330f729Sjoerg   }
6687330f729Sjoerg }
6697330f729Sjoerg 
6707330f729Sjoerg //===----------------------------------------------------------------------===//
6717330f729Sjoerg // Attribute Implementations
6727330f729Sjoerg //===----------------------------------------------------------------------===//
6737330f729Sjoerg 
handlePtGuardedVarAttr(Sema & S,Decl * D,const ParsedAttr & AL)6747330f729Sjoerg static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6757330f729Sjoerg   if (!threadSafetyCheckIsPointer(S, D, AL))
6767330f729Sjoerg     return;
6777330f729Sjoerg 
6787330f729Sjoerg   D->addAttr(::new (S.Context) PtGuardedVarAttr(S.Context, AL));
6797330f729Sjoerg }
6807330f729Sjoerg 
checkGuardedByAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,Expr * & Arg)6817330f729Sjoerg static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
6827330f729Sjoerg                                      Expr *&Arg) {
6837330f729Sjoerg   SmallVector<Expr *, 1> Args;
6847330f729Sjoerg   // check that all arguments are lockable objects
6857330f729Sjoerg   checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
6867330f729Sjoerg   unsigned Size = Args.size();
6877330f729Sjoerg   if (Size != 1)
6887330f729Sjoerg     return false;
6897330f729Sjoerg 
6907330f729Sjoerg   Arg = Args[0];
6917330f729Sjoerg 
6927330f729Sjoerg   return true;
6937330f729Sjoerg }
6947330f729Sjoerg 
handleGuardedByAttr(Sema & S,Decl * D,const ParsedAttr & AL)6957330f729Sjoerg static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6967330f729Sjoerg   Expr *Arg = nullptr;
6977330f729Sjoerg   if (!checkGuardedByAttrCommon(S, D, AL, Arg))
6987330f729Sjoerg     return;
6997330f729Sjoerg 
7007330f729Sjoerg   D->addAttr(::new (S.Context) GuardedByAttr(S.Context, AL, Arg));
7017330f729Sjoerg }
7027330f729Sjoerg 
handlePtGuardedByAttr(Sema & S,Decl * D,const ParsedAttr & AL)7037330f729Sjoerg static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7047330f729Sjoerg   Expr *Arg = nullptr;
7057330f729Sjoerg   if (!checkGuardedByAttrCommon(S, D, AL, Arg))
7067330f729Sjoerg     return;
7077330f729Sjoerg 
7087330f729Sjoerg   if (!threadSafetyCheckIsPointer(S, D, AL))
7097330f729Sjoerg     return;
7107330f729Sjoerg 
7117330f729Sjoerg   D->addAttr(::new (S.Context) PtGuardedByAttr(S.Context, AL, Arg));
7127330f729Sjoerg }
7137330f729Sjoerg 
checkAcquireOrderAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)7147330f729Sjoerg static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
7157330f729Sjoerg                                         SmallVectorImpl<Expr *> &Args) {
716*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1))
7177330f729Sjoerg     return false;
7187330f729Sjoerg 
7197330f729Sjoerg   // Check that this attribute only applies to lockable types.
7207330f729Sjoerg   QualType QT = cast<ValueDecl>(D)->getType();
7217330f729Sjoerg   if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
7227330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) << AL;
7237330f729Sjoerg     return false;
7247330f729Sjoerg   }
7257330f729Sjoerg 
7267330f729Sjoerg   // Check that all arguments are lockable objects.
7277330f729Sjoerg   checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
7287330f729Sjoerg   if (Args.empty())
7297330f729Sjoerg     return false;
7307330f729Sjoerg 
7317330f729Sjoerg   return true;
7327330f729Sjoerg }
7337330f729Sjoerg 
handleAcquiredAfterAttr(Sema & S,Decl * D,const ParsedAttr & AL)7347330f729Sjoerg static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7357330f729Sjoerg   SmallVector<Expr *, 1> Args;
7367330f729Sjoerg   if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
7377330f729Sjoerg     return;
7387330f729Sjoerg 
7397330f729Sjoerg   Expr **StartArg = &Args[0];
7407330f729Sjoerg   D->addAttr(::new (S.Context)
7417330f729Sjoerg                  AcquiredAfterAttr(S.Context, AL, StartArg, Args.size()));
7427330f729Sjoerg }
7437330f729Sjoerg 
handleAcquiredBeforeAttr(Sema & S,Decl * D,const ParsedAttr & AL)7447330f729Sjoerg static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7457330f729Sjoerg   SmallVector<Expr *, 1> Args;
7467330f729Sjoerg   if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
7477330f729Sjoerg     return;
7487330f729Sjoerg 
7497330f729Sjoerg   Expr **StartArg = &Args[0];
7507330f729Sjoerg   D->addAttr(::new (S.Context)
7517330f729Sjoerg                  AcquiredBeforeAttr(S.Context, AL, StartArg, Args.size()));
7527330f729Sjoerg }
7537330f729Sjoerg 
checkLockFunAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)7547330f729Sjoerg static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
7557330f729Sjoerg                                    SmallVectorImpl<Expr *> &Args) {
7567330f729Sjoerg   // zero or more arguments ok
7577330f729Sjoerg   // check that all arguments are lockable objects
7587330f729Sjoerg   checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, /*ParamIdxOk=*/true);
7597330f729Sjoerg 
7607330f729Sjoerg   return true;
7617330f729Sjoerg }
7627330f729Sjoerg 
handleAssertSharedLockAttr(Sema & S,Decl * D,const ParsedAttr & AL)7637330f729Sjoerg static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7647330f729Sjoerg   SmallVector<Expr *, 1> Args;
7657330f729Sjoerg   if (!checkLockFunAttrCommon(S, D, AL, Args))
7667330f729Sjoerg     return;
7677330f729Sjoerg 
7687330f729Sjoerg   unsigned Size = Args.size();
7697330f729Sjoerg   Expr **StartArg = Size == 0 ? nullptr : &Args[0];
7707330f729Sjoerg   D->addAttr(::new (S.Context)
7717330f729Sjoerg                  AssertSharedLockAttr(S.Context, AL, StartArg, Size));
7727330f729Sjoerg }
7737330f729Sjoerg 
handleAssertExclusiveLockAttr(Sema & S,Decl * D,const ParsedAttr & AL)7747330f729Sjoerg static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
7757330f729Sjoerg                                           const ParsedAttr &AL) {
7767330f729Sjoerg   SmallVector<Expr *, 1> Args;
7777330f729Sjoerg   if (!checkLockFunAttrCommon(S, D, AL, Args))
7787330f729Sjoerg     return;
7797330f729Sjoerg 
7807330f729Sjoerg   unsigned Size = Args.size();
7817330f729Sjoerg   Expr **StartArg = Size == 0 ? nullptr : &Args[0];
7827330f729Sjoerg   D->addAttr(::new (S.Context)
7837330f729Sjoerg                  AssertExclusiveLockAttr(S.Context, AL, StartArg, Size));
7847330f729Sjoerg }
7857330f729Sjoerg 
7867330f729Sjoerg /// Checks to be sure that the given parameter number is in bounds, and
7877330f729Sjoerg /// is an integral type. Will emit appropriate diagnostics if this returns
7887330f729Sjoerg /// false.
7897330f729Sjoerg ///
7907330f729Sjoerg /// AttrArgNo is used to actually retrieve the argument, so it's base-0.
7917330f729Sjoerg template <typename AttrInfo>
checkParamIsIntegerType(Sema & S,const Decl * D,const AttrInfo & AI,unsigned AttrArgNo)792*e038c9c4Sjoerg static bool checkParamIsIntegerType(Sema &S, const Decl *D, const AttrInfo &AI,
793*e038c9c4Sjoerg                                     unsigned AttrArgNo) {
7947330f729Sjoerg   assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument");
7957330f729Sjoerg   Expr *AttrArg = AI.getArgAsExpr(AttrArgNo);
7967330f729Sjoerg   ParamIdx Idx;
797*e038c9c4Sjoerg   if (!checkFunctionOrMethodParameterIndex(S, D, AI, AttrArgNo + 1, AttrArg,
7987330f729Sjoerg                                            Idx))
7997330f729Sjoerg     return false;
8007330f729Sjoerg 
801*e038c9c4Sjoerg   QualType ParamTy = getFunctionOrMethodParamType(D, Idx.getASTIndex());
802*e038c9c4Sjoerg   if (!ParamTy->isIntegerType() && !ParamTy->isCharType()) {
8037330f729Sjoerg     SourceLocation SrcLoc = AttrArg->getBeginLoc();
8047330f729Sjoerg     S.Diag(SrcLoc, diag::err_attribute_integers_only)
805*e038c9c4Sjoerg         << AI << getFunctionOrMethodParamRange(D, Idx.getASTIndex());
8067330f729Sjoerg     return false;
8077330f729Sjoerg   }
8087330f729Sjoerg   return true;
8097330f729Sjoerg }
8107330f729Sjoerg 
handleAllocSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)8117330f729Sjoerg static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
812*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
8137330f729Sjoerg     return;
8147330f729Sjoerg 
815*e038c9c4Sjoerg   assert(isFunctionOrMethod(D) && hasFunctionProto(D));
816*e038c9c4Sjoerg 
817*e038c9c4Sjoerg   QualType RetTy = getFunctionOrMethodResultType(D);
818*e038c9c4Sjoerg   if (!RetTy->isPointerType()) {
8197330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL;
8207330f729Sjoerg     return;
8217330f729Sjoerg   }
8227330f729Sjoerg 
8237330f729Sjoerg   const Expr *SizeExpr = AL.getArgAsExpr(0);
8247330f729Sjoerg   int SizeArgNoVal;
8257330f729Sjoerg   // Parameter indices are 1-indexed, hence Index=1
8267330f729Sjoerg   if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Idx=*/1))
8277330f729Sjoerg     return;
828*e038c9c4Sjoerg   if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/0))
8297330f729Sjoerg     return;
8307330f729Sjoerg   ParamIdx SizeArgNo(SizeArgNoVal, D);
8317330f729Sjoerg 
8327330f729Sjoerg   ParamIdx NumberArgNo;
8337330f729Sjoerg   if (AL.getNumArgs() == 2) {
8347330f729Sjoerg     const Expr *NumberExpr = AL.getArgAsExpr(1);
8357330f729Sjoerg     int Val;
8367330f729Sjoerg     // Parameter indices are 1-based, hence Index=2
8377330f729Sjoerg     if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Idx=*/2))
8387330f729Sjoerg       return;
839*e038c9c4Sjoerg     if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/1))
8407330f729Sjoerg       return;
8417330f729Sjoerg     NumberArgNo = ParamIdx(Val, D);
8427330f729Sjoerg   }
8437330f729Sjoerg 
8447330f729Sjoerg   D->addAttr(::new (S.Context)
8457330f729Sjoerg                  AllocSizeAttr(S.Context, AL, SizeArgNo, NumberArgNo));
8467330f729Sjoerg }
8477330f729Sjoerg 
checkTryLockFunAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)8487330f729Sjoerg static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
8497330f729Sjoerg                                       SmallVectorImpl<Expr *> &Args) {
850*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1))
8517330f729Sjoerg     return false;
8527330f729Sjoerg 
8537330f729Sjoerg   if (!isIntOrBool(AL.getArgAsExpr(0))) {
8547330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
8557330f729Sjoerg         << AL << 1 << AANT_ArgumentIntOrBool;
8567330f729Sjoerg     return false;
8577330f729Sjoerg   }
8587330f729Sjoerg 
8597330f729Sjoerg   // check that all arguments are lockable objects
8607330f729Sjoerg   checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 1);
8617330f729Sjoerg 
8627330f729Sjoerg   return true;
8637330f729Sjoerg }
8647330f729Sjoerg 
handleSharedTrylockFunctionAttr(Sema & S,Decl * D,const ParsedAttr & AL)8657330f729Sjoerg static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
8667330f729Sjoerg                                             const ParsedAttr &AL) {
8677330f729Sjoerg   SmallVector<Expr*, 2> Args;
8687330f729Sjoerg   if (!checkTryLockFunAttrCommon(S, D, AL, Args))
8697330f729Sjoerg     return;
8707330f729Sjoerg 
8717330f729Sjoerg   D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(
8727330f729Sjoerg       S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size()));
8737330f729Sjoerg }
8747330f729Sjoerg 
handleExclusiveTrylockFunctionAttr(Sema & S,Decl * D,const ParsedAttr & AL)8757330f729Sjoerg static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
8767330f729Sjoerg                                                const ParsedAttr &AL) {
8777330f729Sjoerg   SmallVector<Expr*, 2> Args;
8787330f729Sjoerg   if (!checkTryLockFunAttrCommon(S, D, AL, Args))
8797330f729Sjoerg     return;
8807330f729Sjoerg 
8817330f729Sjoerg   D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(
8827330f729Sjoerg       S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size()));
8837330f729Sjoerg }
8847330f729Sjoerg 
handleLockReturnedAttr(Sema & S,Decl * D,const ParsedAttr & AL)8857330f729Sjoerg static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
8867330f729Sjoerg   // check that the argument is lockable object
8877330f729Sjoerg   SmallVector<Expr*, 1> Args;
8887330f729Sjoerg   checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
8897330f729Sjoerg   unsigned Size = Args.size();
8907330f729Sjoerg   if (Size == 0)
8917330f729Sjoerg     return;
8927330f729Sjoerg 
8937330f729Sjoerg   D->addAttr(::new (S.Context) LockReturnedAttr(S.Context, AL, Args[0]));
8947330f729Sjoerg }
8957330f729Sjoerg 
handleLocksExcludedAttr(Sema & S,Decl * D,const ParsedAttr & AL)8967330f729Sjoerg static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
897*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1))
8987330f729Sjoerg     return;
8997330f729Sjoerg 
9007330f729Sjoerg   // check that all arguments are lockable objects
9017330f729Sjoerg   SmallVector<Expr*, 1> Args;
9027330f729Sjoerg   checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
9037330f729Sjoerg   unsigned Size = Args.size();
9047330f729Sjoerg   if (Size == 0)
9057330f729Sjoerg     return;
9067330f729Sjoerg   Expr **StartArg = &Args[0];
9077330f729Sjoerg 
9087330f729Sjoerg   D->addAttr(::new (S.Context)
9097330f729Sjoerg                  LocksExcludedAttr(S.Context, AL, StartArg, Size));
9107330f729Sjoerg }
9117330f729Sjoerg 
checkFunctionConditionAttr(Sema & S,Decl * D,const ParsedAttr & AL,Expr * & Cond,StringRef & Msg)9127330f729Sjoerg static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL,
9137330f729Sjoerg                                        Expr *&Cond, StringRef &Msg) {
9147330f729Sjoerg   Cond = AL.getArgAsExpr(0);
9157330f729Sjoerg   if (!Cond->isTypeDependent()) {
9167330f729Sjoerg     ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
9177330f729Sjoerg     if (Converted.isInvalid())
9187330f729Sjoerg       return false;
9197330f729Sjoerg     Cond = Converted.get();
9207330f729Sjoerg   }
9217330f729Sjoerg 
9227330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 1, Msg))
9237330f729Sjoerg     return false;
9247330f729Sjoerg 
9257330f729Sjoerg   if (Msg.empty())
9267330f729Sjoerg     Msg = "<no message provided>";
9277330f729Sjoerg 
9287330f729Sjoerg   SmallVector<PartialDiagnosticAt, 8> Diags;
9297330f729Sjoerg   if (isa<FunctionDecl>(D) && !Cond->isValueDependent() &&
9307330f729Sjoerg       !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
9317330f729Sjoerg                                                 Diags)) {
9327330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) << AL;
9337330f729Sjoerg     for (const PartialDiagnosticAt &PDiag : Diags)
9347330f729Sjoerg       S.Diag(PDiag.first, PDiag.second);
9357330f729Sjoerg     return false;
9367330f729Sjoerg   }
9377330f729Sjoerg   return true;
9387330f729Sjoerg }
9397330f729Sjoerg 
handleEnableIfAttr(Sema & S,Decl * D,const ParsedAttr & AL)9407330f729Sjoerg static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
9417330f729Sjoerg   S.Diag(AL.getLoc(), diag::ext_clang_enable_if);
9427330f729Sjoerg 
9437330f729Sjoerg   Expr *Cond;
9447330f729Sjoerg   StringRef Msg;
9457330f729Sjoerg   if (checkFunctionConditionAttr(S, D, AL, Cond, Msg))
9467330f729Sjoerg     D->addAttr(::new (S.Context) EnableIfAttr(S.Context, AL, Cond, Msg));
9477330f729Sjoerg }
9487330f729Sjoerg 
9497330f729Sjoerg namespace {
9507330f729Sjoerg /// Determines if a given Expr references any of the given function's
9517330f729Sjoerg /// ParmVarDecls, or the function's implicit `this` parameter (if applicable).
9527330f729Sjoerg class ArgumentDependenceChecker
9537330f729Sjoerg     : public RecursiveASTVisitor<ArgumentDependenceChecker> {
9547330f729Sjoerg #ifndef NDEBUG
9557330f729Sjoerg   const CXXRecordDecl *ClassType;
9567330f729Sjoerg #endif
9577330f729Sjoerg   llvm::SmallPtrSet<const ParmVarDecl *, 16> Parms;
9587330f729Sjoerg   bool Result;
9597330f729Sjoerg 
9607330f729Sjoerg public:
ArgumentDependenceChecker(const FunctionDecl * FD)9617330f729Sjoerg   ArgumentDependenceChecker(const FunctionDecl *FD) {
9627330f729Sjoerg #ifndef NDEBUG
9637330f729Sjoerg     if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
9647330f729Sjoerg       ClassType = MD->getParent();
9657330f729Sjoerg     else
9667330f729Sjoerg       ClassType = nullptr;
9677330f729Sjoerg #endif
9687330f729Sjoerg     Parms.insert(FD->param_begin(), FD->param_end());
9697330f729Sjoerg   }
9707330f729Sjoerg 
referencesArgs(Expr * E)9717330f729Sjoerg   bool referencesArgs(Expr *E) {
9727330f729Sjoerg     Result = false;
9737330f729Sjoerg     TraverseStmt(E);
9747330f729Sjoerg     return Result;
9757330f729Sjoerg   }
9767330f729Sjoerg 
VisitCXXThisExpr(CXXThisExpr * E)9777330f729Sjoerg   bool VisitCXXThisExpr(CXXThisExpr *E) {
9787330f729Sjoerg     assert(E->getType()->getPointeeCXXRecordDecl() == ClassType &&
9797330f729Sjoerg            "`this` doesn't refer to the enclosing class?");
9807330f729Sjoerg     Result = true;
9817330f729Sjoerg     return false;
9827330f729Sjoerg   }
9837330f729Sjoerg 
VisitDeclRefExpr(DeclRefExpr * DRE)9847330f729Sjoerg   bool VisitDeclRefExpr(DeclRefExpr *DRE) {
9857330f729Sjoerg     if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
9867330f729Sjoerg       if (Parms.count(PVD)) {
9877330f729Sjoerg         Result = true;
9887330f729Sjoerg         return false;
9897330f729Sjoerg       }
9907330f729Sjoerg     return true;
9917330f729Sjoerg   }
9927330f729Sjoerg };
9937330f729Sjoerg }
9947330f729Sjoerg 
handleDiagnoseIfAttr(Sema & S,Decl * D,const ParsedAttr & AL)9957330f729Sjoerg static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
9967330f729Sjoerg   S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if);
9977330f729Sjoerg 
9987330f729Sjoerg   Expr *Cond;
9997330f729Sjoerg   StringRef Msg;
10007330f729Sjoerg   if (!checkFunctionConditionAttr(S, D, AL, Cond, Msg))
10017330f729Sjoerg     return;
10027330f729Sjoerg 
10037330f729Sjoerg   StringRef DiagTypeStr;
10047330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 2, DiagTypeStr))
10057330f729Sjoerg     return;
10067330f729Sjoerg 
10077330f729Sjoerg   DiagnoseIfAttr::DiagnosticType DiagType;
10087330f729Sjoerg   if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) {
10097330f729Sjoerg     S.Diag(AL.getArgAsExpr(2)->getBeginLoc(),
10107330f729Sjoerg            diag::err_diagnose_if_invalid_diagnostic_type);
10117330f729Sjoerg     return;
10127330f729Sjoerg   }
10137330f729Sjoerg 
10147330f729Sjoerg   bool ArgDependent = false;
10157330f729Sjoerg   if (const auto *FD = dyn_cast<FunctionDecl>(D))
10167330f729Sjoerg     ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond);
10177330f729Sjoerg   D->addAttr(::new (S.Context) DiagnoseIfAttr(
10187330f729Sjoerg       S.Context, AL, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D)));
10197330f729Sjoerg }
10207330f729Sjoerg 
handleNoBuiltinAttr(Sema & S,Decl * D,const ParsedAttr & AL)1021*e038c9c4Sjoerg static void handleNoBuiltinAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1022*e038c9c4Sjoerg   static constexpr const StringRef kWildcard = "*";
1023*e038c9c4Sjoerg 
1024*e038c9c4Sjoerg   llvm::SmallVector<StringRef, 16> Names;
1025*e038c9c4Sjoerg   bool HasWildcard = false;
1026*e038c9c4Sjoerg 
1027*e038c9c4Sjoerg   const auto AddBuiltinName = [&Names, &HasWildcard](StringRef Name) {
1028*e038c9c4Sjoerg     if (Name == kWildcard)
1029*e038c9c4Sjoerg       HasWildcard = true;
1030*e038c9c4Sjoerg     Names.push_back(Name);
1031*e038c9c4Sjoerg   };
1032*e038c9c4Sjoerg 
1033*e038c9c4Sjoerg   // Add previously defined attributes.
1034*e038c9c4Sjoerg   if (const auto *NBA = D->getAttr<NoBuiltinAttr>())
1035*e038c9c4Sjoerg     for (StringRef BuiltinName : NBA->builtinNames())
1036*e038c9c4Sjoerg       AddBuiltinName(BuiltinName);
1037*e038c9c4Sjoerg 
1038*e038c9c4Sjoerg   // Add current attributes.
1039*e038c9c4Sjoerg   if (AL.getNumArgs() == 0)
1040*e038c9c4Sjoerg     AddBuiltinName(kWildcard);
1041*e038c9c4Sjoerg   else
1042*e038c9c4Sjoerg     for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1043*e038c9c4Sjoerg       StringRef BuiltinName;
1044*e038c9c4Sjoerg       SourceLocation LiteralLoc;
1045*e038c9c4Sjoerg       if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, &LiteralLoc))
1046*e038c9c4Sjoerg         return;
1047*e038c9c4Sjoerg 
1048*e038c9c4Sjoerg       if (Builtin::Context::isBuiltinFunc(BuiltinName))
1049*e038c9c4Sjoerg         AddBuiltinName(BuiltinName);
1050*e038c9c4Sjoerg       else
1051*e038c9c4Sjoerg         S.Diag(LiteralLoc, diag::warn_attribute_no_builtin_invalid_builtin_name)
1052*e038c9c4Sjoerg             << BuiltinName << AL;
1053*e038c9c4Sjoerg     }
1054*e038c9c4Sjoerg 
1055*e038c9c4Sjoerg   // Repeating the same attribute is fine.
1056*e038c9c4Sjoerg   llvm::sort(Names);
1057*e038c9c4Sjoerg   Names.erase(std::unique(Names.begin(), Names.end()), Names.end());
1058*e038c9c4Sjoerg 
1059*e038c9c4Sjoerg   // Empty no_builtin must be on its own.
1060*e038c9c4Sjoerg   if (HasWildcard && Names.size() > 1)
1061*e038c9c4Sjoerg     S.Diag(D->getLocation(),
1062*e038c9c4Sjoerg            diag::err_attribute_no_builtin_wildcard_or_builtin_name)
1063*e038c9c4Sjoerg         << AL;
1064*e038c9c4Sjoerg 
1065*e038c9c4Sjoerg   if (D->hasAttr<NoBuiltinAttr>())
1066*e038c9c4Sjoerg     D->dropAttr<NoBuiltinAttr>();
1067*e038c9c4Sjoerg   D->addAttr(::new (S.Context)
1068*e038c9c4Sjoerg                  NoBuiltinAttr(S.Context, AL, Names.data(), Names.size()));
1069*e038c9c4Sjoerg }
1070*e038c9c4Sjoerg 
handlePassObjectSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)10717330f729Sjoerg static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
10727330f729Sjoerg   if (D->hasAttr<PassObjectSizeAttr>()) {
10737330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL;
10747330f729Sjoerg     return;
10757330f729Sjoerg   }
10767330f729Sjoerg 
10777330f729Sjoerg   Expr *E = AL.getArgAsExpr(0);
10787330f729Sjoerg   uint32_t Type;
10797330f729Sjoerg   if (!checkUInt32Argument(S, AL, E, Type, /*Idx=*/1))
10807330f729Sjoerg     return;
10817330f729Sjoerg 
10827330f729Sjoerg   // pass_object_size's argument is passed in as the second argument of
10837330f729Sjoerg   // __builtin_object_size. So, it has the same constraints as that second
10847330f729Sjoerg   // argument; namely, it must be in the range [0, 3].
10857330f729Sjoerg   if (Type > 3) {
10867330f729Sjoerg     S.Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range)
10877330f729Sjoerg         << AL << 0 << 3 << E->getSourceRange();
10887330f729Sjoerg     return;
10897330f729Sjoerg   }
10907330f729Sjoerg 
10917330f729Sjoerg   // pass_object_size is only supported on constant pointer parameters; as a
10927330f729Sjoerg   // kindness to users, we allow the parameter to be non-const for declarations.
10937330f729Sjoerg   // At this point, we have no clue if `D` belongs to a function declaration or
10947330f729Sjoerg   // definition, so we defer the constness check until later.
10957330f729Sjoerg   if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) {
10967330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::err_attribute_pointers_only) << AL << 1;
10977330f729Sjoerg     return;
10987330f729Sjoerg   }
10997330f729Sjoerg 
11007330f729Sjoerg   D->addAttr(::new (S.Context) PassObjectSizeAttr(S.Context, AL, (int)Type));
11017330f729Sjoerg }
11027330f729Sjoerg 
handleConsumableAttr(Sema & S,Decl * D,const ParsedAttr & AL)11037330f729Sjoerg static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
11047330f729Sjoerg   ConsumableAttr::ConsumedState DefaultState;
11057330f729Sjoerg 
11067330f729Sjoerg   if (AL.isArgIdent(0)) {
11077330f729Sjoerg     IdentifierLoc *IL = AL.getArgAsIdent(0);
11087330f729Sjoerg     if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
11097330f729Sjoerg                                                    DefaultState)) {
11107330f729Sjoerg       S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
11117330f729Sjoerg                                                                << IL->Ident;
11127330f729Sjoerg       return;
11137330f729Sjoerg     }
11147330f729Sjoerg   } else {
11157330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
11167330f729Sjoerg         << AL << AANT_ArgumentIdentifier;
11177330f729Sjoerg     return;
11187330f729Sjoerg   }
11197330f729Sjoerg 
11207330f729Sjoerg   D->addAttr(::new (S.Context) ConsumableAttr(S.Context, AL, DefaultState));
11217330f729Sjoerg }
11227330f729Sjoerg 
checkForConsumableClass(Sema & S,const CXXMethodDecl * MD,const ParsedAttr & AL)11237330f729Sjoerg static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
11247330f729Sjoerg                                     const ParsedAttr &AL) {
11257330f729Sjoerg   QualType ThisType = MD->getThisType()->getPointeeType();
11267330f729Sjoerg 
11277330f729Sjoerg   if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
11287330f729Sjoerg     if (!RD->hasAttr<ConsumableAttr>()) {
1129*e038c9c4Sjoerg       S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) << RD;
11307330f729Sjoerg 
11317330f729Sjoerg       return false;
11327330f729Sjoerg     }
11337330f729Sjoerg   }
11347330f729Sjoerg 
11357330f729Sjoerg   return true;
11367330f729Sjoerg }
11377330f729Sjoerg 
handleCallableWhenAttr(Sema & S,Decl * D,const ParsedAttr & AL)11387330f729Sjoerg static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1139*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1))
11407330f729Sjoerg     return;
11417330f729Sjoerg 
11427330f729Sjoerg   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
11437330f729Sjoerg     return;
11447330f729Sjoerg 
11457330f729Sjoerg   SmallVector<CallableWhenAttr::ConsumedState, 3> States;
11467330f729Sjoerg   for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) {
11477330f729Sjoerg     CallableWhenAttr::ConsumedState CallableState;
11487330f729Sjoerg 
11497330f729Sjoerg     StringRef StateString;
11507330f729Sjoerg     SourceLocation Loc;
11517330f729Sjoerg     if (AL.isArgIdent(ArgIndex)) {
11527330f729Sjoerg       IdentifierLoc *Ident = AL.getArgAsIdent(ArgIndex);
11537330f729Sjoerg       StateString = Ident->Ident->getName();
11547330f729Sjoerg       Loc = Ident->Loc;
11557330f729Sjoerg     } else {
11567330f729Sjoerg       if (!S.checkStringLiteralArgumentAttr(AL, ArgIndex, StateString, &Loc))
11577330f729Sjoerg         return;
11587330f729Sjoerg     }
11597330f729Sjoerg 
11607330f729Sjoerg     if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
11617330f729Sjoerg                                                      CallableState)) {
11627330f729Sjoerg       S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << StateString;
11637330f729Sjoerg       return;
11647330f729Sjoerg     }
11657330f729Sjoerg 
11667330f729Sjoerg     States.push_back(CallableState);
11677330f729Sjoerg   }
11687330f729Sjoerg 
11697330f729Sjoerg   D->addAttr(::new (S.Context)
11707330f729Sjoerg                  CallableWhenAttr(S.Context, AL, States.data(), States.size()));
11717330f729Sjoerg }
11727330f729Sjoerg 
handleParamTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)11737330f729Sjoerg static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
11747330f729Sjoerg   ParamTypestateAttr::ConsumedState ParamState;
11757330f729Sjoerg 
11767330f729Sjoerg   if (AL.isArgIdent(0)) {
11777330f729Sjoerg     IdentifierLoc *Ident = AL.getArgAsIdent(0);
11787330f729Sjoerg     StringRef StateString = Ident->Ident->getName();
11797330f729Sjoerg 
11807330f729Sjoerg     if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
11817330f729Sjoerg                                                        ParamState)) {
11827330f729Sjoerg       S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
11837330f729Sjoerg           << AL << StateString;
11847330f729Sjoerg       return;
11857330f729Sjoerg     }
11867330f729Sjoerg   } else {
11877330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
11887330f729Sjoerg         << AL << AANT_ArgumentIdentifier;
11897330f729Sjoerg     return;
11907330f729Sjoerg   }
11917330f729Sjoerg 
11927330f729Sjoerg   // FIXME: This check is currently being done in the analysis.  It can be
11937330f729Sjoerg   //        enabled here only after the parser propagates attributes at
11947330f729Sjoerg   //        template specialization definition, not declaration.
11957330f729Sjoerg   //QualType ReturnType = cast<ParmVarDecl>(D)->getType();
11967330f729Sjoerg   //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
11977330f729Sjoerg   //
11987330f729Sjoerg   //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
11997330f729Sjoerg   //    S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
12007330f729Sjoerg   //      ReturnType.getAsString();
12017330f729Sjoerg   //    return;
12027330f729Sjoerg   //}
12037330f729Sjoerg 
12047330f729Sjoerg   D->addAttr(::new (S.Context) ParamTypestateAttr(S.Context, AL, ParamState));
12057330f729Sjoerg }
12067330f729Sjoerg 
handleReturnTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)12077330f729Sjoerg static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12087330f729Sjoerg   ReturnTypestateAttr::ConsumedState ReturnState;
12097330f729Sjoerg 
12107330f729Sjoerg   if (AL.isArgIdent(0)) {
12117330f729Sjoerg     IdentifierLoc *IL = AL.getArgAsIdent(0);
12127330f729Sjoerg     if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
12137330f729Sjoerg                                                         ReturnState)) {
12147330f729Sjoerg       S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
12157330f729Sjoerg                                                                << IL->Ident;
12167330f729Sjoerg       return;
12177330f729Sjoerg     }
12187330f729Sjoerg   } else {
12197330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
12207330f729Sjoerg         << AL << AANT_ArgumentIdentifier;
12217330f729Sjoerg     return;
12227330f729Sjoerg   }
12237330f729Sjoerg 
12247330f729Sjoerg   // FIXME: This check is currently being done in the analysis.  It can be
12257330f729Sjoerg   //        enabled here only after the parser propagates attributes at
12267330f729Sjoerg   //        template specialization definition, not declaration.
12277330f729Sjoerg   //QualType ReturnType;
12287330f729Sjoerg   //
12297330f729Sjoerg   //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) {
12307330f729Sjoerg   //  ReturnType = Param->getType();
12317330f729Sjoerg   //
12327330f729Sjoerg   //} else if (const CXXConstructorDecl *Constructor =
12337330f729Sjoerg   //             dyn_cast<CXXConstructorDecl>(D)) {
12347330f729Sjoerg   //  ReturnType = Constructor->getThisType()->getPointeeType();
12357330f729Sjoerg   //
12367330f729Sjoerg   //} else {
12377330f729Sjoerg   //
12387330f729Sjoerg   //  ReturnType = cast<FunctionDecl>(D)->getCallResultType();
12397330f729Sjoerg   //}
12407330f729Sjoerg   //
12417330f729Sjoerg   //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
12427330f729Sjoerg   //
12437330f729Sjoerg   //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
12447330f729Sjoerg   //    S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
12457330f729Sjoerg   //      ReturnType.getAsString();
12467330f729Sjoerg   //    return;
12477330f729Sjoerg   //}
12487330f729Sjoerg 
12497330f729Sjoerg   D->addAttr(::new (S.Context) ReturnTypestateAttr(S.Context, AL, ReturnState));
12507330f729Sjoerg }
12517330f729Sjoerg 
handleSetTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)12527330f729Sjoerg static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12537330f729Sjoerg   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
12547330f729Sjoerg     return;
12557330f729Sjoerg 
12567330f729Sjoerg   SetTypestateAttr::ConsumedState NewState;
12577330f729Sjoerg   if (AL.isArgIdent(0)) {
12587330f729Sjoerg     IdentifierLoc *Ident = AL.getArgAsIdent(0);
12597330f729Sjoerg     StringRef Param = Ident->Ident->getName();
12607330f729Sjoerg     if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) {
12617330f729Sjoerg       S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
12627330f729Sjoerg                                                                   << Param;
12637330f729Sjoerg       return;
12647330f729Sjoerg     }
12657330f729Sjoerg   } else {
12667330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
12677330f729Sjoerg         << AL << AANT_ArgumentIdentifier;
12687330f729Sjoerg     return;
12697330f729Sjoerg   }
12707330f729Sjoerg 
12717330f729Sjoerg   D->addAttr(::new (S.Context) SetTypestateAttr(S.Context, AL, NewState));
12727330f729Sjoerg }
12737330f729Sjoerg 
handleTestTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)12747330f729Sjoerg static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12757330f729Sjoerg   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
12767330f729Sjoerg     return;
12777330f729Sjoerg 
12787330f729Sjoerg   TestTypestateAttr::ConsumedState TestState;
12797330f729Sjoerg   if (AL.isArgIdent(0)) {
12807330f729Sjoerg     IdentifierLoc *Ident = AL.getArgAsIdent(0);
12817330f729Sjoerg     StringRef Param = Ident->Ident->getName();
12827330f729Sjoerg     if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) {
12837330f729Sjoerg       S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
12847330f729Sjoerg                                                                   << Param;
12857330f729Sjoerg       return;
12867330f729Sjoerg     }
12877330f729Sjoerg   } else {
12887330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
12897330f729Sjoerg         << AL << AANT_ArgumentIdentifier;
12907330f729Sjoerg     return;
12917330f729Sjoerg   }
12927330f729Sjoerg 
12937330f729Sjoerg   D->addAttr(::new (S.Context) TestTypestateAttr(S.Context, AL, TestState));
12947330f729Sjoerg }
12957330f729Sjoerg 
handleExtVectorTypeAttr(Sema & S,Decl * D,const ParsedAttr & AL)12967330f729Sjoerg static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12977330f729Sjoerg   // Remember this typedef decl, we will need it later for diagnostics.
12987330f729Sjoerg   S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
12997330f729Sjoerg }
13007330f729Sjoerg 
handlePackedAttr(Sema & S,Decl * D,const ParsedAttr & AL)13017330f729Sjoerg static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
13027330f729Sjoerg   if (auto *TD = dyn_cast<TagDecl>(D))
13037330f729Sjoerg     TD->addAttr(::new (S.Context) PackedAttr(S.Context, AL));
13047330f729Sjoerg   else if (auto *FD = dyn_cast<FieldDecl>(D)) {
13057330f729Sjoerg     bool BitfieldByteAligned = (!FD->getType()->isDependentType() &&
13067330f729Sjoerg                                 !FD->getType()->isIncompleteType() &&
13077330f729Sjoerg                                 FD->isBitField() &&
13087330f729Sjoerg                                 S.Context.getTypeAlign(FD->getType()) <= 8);
13097330f729Sjoerg 
13107330f729Sjoerg     if (S.getASTContext().getTargetInfo().getTriple().isPS4()) {
13117330f729Sjoerg       if (BitfieldByteAligned)
13127330f729Sjoerg         // The PS4 target needs to maintain ABI backwards compatibility.
13137330f729Sjoerg         S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
13147330f729Sjoerg             << AL << FD->getType();
13157330f729Sjoerg       else
13167330f729Sjoerg         FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL));
13177330f729Sjoerg     } else {
13187330f729Sjoerg       // Report warning about changed offset in the newer compiler versions.
13197330f729Sjoerg       if (BitfieldByteAligned)
13207330f729Sjoerg         S.Diag(AL.getLoc(), diag::warn_attribute_packed_for_bitfield);
13217330f729Sjoerg 
13227330f729Sjoerg       FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL));
13237330f729Sjoerg     }
13247330f729Sjoerg 
13257330f729Sjoerg   } else
13267330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
13277330f729Sjoerg }
13287330f729Sjoerg 
handlePreferredName(Sema & S,Decl * D,const ParsedAttr & AL)1329*e038c9c4Sjoerg static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) {
1330*e038c9c4Sjoerg   auto *RD = cast<CXXRecordDecl>(D);
1331*e038c9c4Sjoerg   ClassTemplateDecl *CTD = RD->getDescribedClassTemplate();
1332*e038c9c4Sjoerg   assert(CTD && "attribute does not appertain to this declaration");
1333*e038c9c4Sjoerg 
1334*e038c9c4Sjoerg   ParsedType PT = AL.getTypeArg();
1335*e038c9c4Sjoerg   TypeSourceInfo *TSI = nullptr;
1336*e038c9c4Sjoerg   QualType T = S.GetTypeFromParser(PT, &TSI);
1337*e038c9c4Sjoerg   if (!TSI)
1338*e038c9c4Sjoerg     TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc());
1339*e038c9c4Sjoerg 
1340*e038c9c4Sjoerg   if (!T.hasQualifiers() && T->isTypedefNameType()) {
1341*e038c9c4Sjoerg     // Find the template name, if this type names a template specialization.
1342*e038c9c4Sjoerg     const TemplateDecl *Template = nullptr;
1343*e038c9c4Sjoerg     if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
1344*e038c9c4Sjoerg             T->getAsCXXRecordDecl())) {
1345*e038c9c4Sjoerg       Template = CTSD->getSpecializedTemplate();
1346*e038c9c4Sjoerg     } else if (const auto *TST = T->getAs<TemplateSpecializationType>()) {
1347*e038c9c4Sjoerg       while (TST && TST->isTypeAlias())
1348*e038c9c4Sjoerg         TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
1349*e038c9c4Sjoerg       if (TST)
1350*e038c9c4Sjoerg         Template = TST->getTemplateName().getAsTemplateDecl();
1351*e038c9c4Sjoerg     }
1352*e038c9c4Sjoerg 
1353*e038c9c4Sjoerg     if (Template && declaresSameEntity(Template, CTD)) {
1354*e038c9c4Sjoerg       D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI));
1355*e038c9c4Sjoerg       return;
1356*e038c9c4Sjoerg     }
1357*e038c9c4Sjoerg   }
1358*e038c9c4Sjoerg 
1359*e038c9c4Sjoerg   S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid)
1360*e038c9c4Sjoerg       << T << CTD;
1361*e038c9c4Sjoerg   if (const auto *TT = T->getAs<TypedefType>())
1362*e038c9c4Sjoerg     S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at)
1363*e038c9c4Sjoerg         << TT->getDecl();
1364*e038c9c4Sjoerg }
1365*e038c9c4Sjoerg 
checkIBOutletCommon(Sema & S,Decl * D,const ParsedAttr & AL)13667330f729Sjoerg static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
13677330f729Sjoerg   // The IBOutlet/IBOutletCollection attributes only apply to instance
13687330f729Sjoerg   // variables or properties of Objective-C classes.  The outlet must also
13697330f729Sjoerg   // have an object reference type.
13707330f729Sjoerg   if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {
13717330f729Sjoerg     if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
13727330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
13737330f729Sjoerg           << AL << VD->getType() << 0;
13747330f729Sjoerg       return false;
13757330f729Sjoerg     }
13767330f729Sjoerg   }
13777330f729Sjoerg   else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
13787330f729Sjoerg     if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
13797330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
13807330f729Sjoerg           << AL << PD->getType() << 1;
13817330f729Sjoerg       return false;
13827330f729Sjoerg     }
13837330f729Sjoerg   }
13847330f729Sjoerg   else {
13857330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL;
13867330f729Sjoerg     return false;
13877330f729Sjoerg   }
13887330f729Sjoerg 
13897330f729Sjoerg   return true;
13907330f729Sjoerg }
13917330f729Sjoerg 
handleIBOutlet(Sema & S,Decl * D,const ParsedAttr & AL)13927330f729Sjoerg static void handleIBOutlet(Sema &S, Decl *D, const ParsedAttr &AL) {
13937330f729Sjoerg   if (!checkIBOutletCommon(S, D, AL))
13947330f729Sjoerg     return;
13957330f729Sjoerg 
13967330f729Sjoerg   D->addAttr(::new (S.Context) IBOutletAttr(S.Context, AL));
13977330f729Sjoerg }
13987330f729Sjoerg 
handleIBOutletCollection(Sema & S,Decl * D,const ParsedAttr & AL)13997330f729Sjoerg static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) {
14007330f729Sjoerg 
14017330f729Sjoerg   // The iboutletcollection attribute can have zero or one arguments.
14027330f729Sjoerg   if (AL.getNumArgs() > 1) {
14037330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
14047330f729Sjoerg     return;
14057330f729Sjoerg   }
14067330f729Sjoerg 
14077330f729Sjoerg   if (!checkIBOutletCommon(S, D, AL))
14087330f729Sjoerg     return;
14097330f729Sjoerg 
14107330f729Sjoerg   ParsedType PT;
14117330f729Sjoerg 
14127330f729Sjoerg   if (AL.hasParsedType())
14137330f729Sjoerg     PT = AL.getTypeArg();
14147330f729Sjoerg   else {
14157330f729Sjoerg     PT = S.getTypeName(S.Context.Idents.get("NSObject"), AL.getLoc(),
14167330f729Sjoerg                        S.getScopeForContext(D->getDeclContext()->getParent()));
14177330f729Sjoerg     if (!PT) {
14187330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
14197330f729Sjoerg       return;
14207330f729Sjoerg     }
14217330f729Sjoerg   }
14227330f729Sjoerg 
14237330f729Sjoerg   TypeSourceInfo *QTLoc = nullptr;
14247330f729Sjoerg   QualType QT = S.GetTypeFromParser(PT, &QTLoc);
14257330f729Sjoerg   if (!QTLoc)
14267330f729Sjoerg     QTLoc = S.Context.getTrivialTypeSourceInfo(QT, AL.getLoc());
14277330f729Sjoerg 
14287330f729Sjoerg   // Diagnose use of non-object type in iboutletcollection attribute.
14297330f729Sjoerg   // FIXME. Gnu attribute extension ignores use of builtin types in
14307330f729Sjoerg   // attributes. So, __attribute__((iboutletcollection(char))) will be
14317330f729Sjoerg   // treated as __attribute__((iboutletcollection())).
14327330f729Sjoerg   if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
14337330f729Sjoerg     S.Diag(AL.getLoc(),
14347330f729Sjoerg            QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype
14357330f729Sjoerg                                : diag::err_iboutletcollection_type) << QT;
14367330f729Sjoerg     return;
14377330f729Sjoerg   }
14387330f729Sjoerg 
14397330f729Sjoerg   D->addAttr(::new (S.Context) IBOutletCollectionAttr(S.Context, AL, QTLoc));
14407330f729Sjoerg }
14417330f729Sjoerg 
isValidPointerAttrType(QualType T,bool RefOkay)14427330f729Sjoerg bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
14437330f729Sjoerg   if (RefOkay) {
14447330f729Sjoerg     if (T->isReferenceType())
14457330f729Sjoerg       return true;
14467330f729Sjoerg   } else {
14477330f729Sjoerg     T = T.getNonReferenceType();
14487330f729Sjoerg   }
14497330f729Sjoerg 
14507330f729Sjoerg   // The nonnull attribute, and other similar attributes, can be applied to a
14517330f729Sjoerg   // transparent union that contains a pointer type.
14527330f729Sjoerg   if (const RecordType *UT = T->getAsUnionType()) {
14537330f729Sjoerg     if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
14547330f729Sjoerg       RecordDecl *UD = UT->getDecl();
14557330f729Sjoerg       for (const auto *I : UD->fields()) {
14567330f729Sjoerg         QualType QT = I->getType();
14577330f729Sjoerg         if (QT->isAnyPointerType() || QT->isBlockPointerType())
14587330f729Sjoerg           return true;
14597330f729Sjoerg       }
14607330f729Sjoerg     }
14617330f729Sjoerg   }
14627330f729Sjoerg 
14637330f729Sjoerg   return T->isAnyPointerType() || T->isBlockPointerType();
14647330f729Sjoerg }
14657330f729Sjoerg 
attrNonNullArgCheck(Sema & S,QualType T,const ParsedAttr & AL,SourceRange AttrParmRange,SourceRange TypeRange,bool isReturnValue=false)14667330f729Sjoerg static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL,
14677330f729Sjoerg                                 SourceRange AttrParmRange,
14687330f729Sjoerg                                 SourceRange TypeRange,
14697330f729Sjoerg                                 bool isReturnValue = false) {
14707330f729Sjoerg   if (!S.isValidPointerAttrType(T)) {
14717330f729Sjoerg     if (isReturnValue)
14727330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
14737330f729Sjoerg           << AL << AttrParmRange << TypeRange;
14747330f729Sjoerg     else
14757330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
14767330f729Sjoerg           << AL << AttrParmRange << TypeRange << 0;
14777330f729Sjoerg     return false;
14787330f729Sjoerg   }
14797330f729Sjoerg   return true;
14807330f729Sjoerg }
14817330f729Sjoerg 
handleNonNullAttr(Sema & S,Decl * D,const ParsedAttr & AL)14827330f729Sjoerg static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
14837330f729Sjoerg   SmallVector<ParamIdx, 8> NonNullArgs;
14847330f729Sjoerg   for (unsigned I = 0; I < AL.getNumArgs(); ++I) {
14857330f729Sjoerg     Expr *Ex = AL.getArgAsExpr(I);
14867330f729Sjoerg     ParamIdx Idx;
14877330f729Sjoerg     if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx))
14887330f729Sjoerg       return;
14897330f729Sjoerg 
14907330f729Sjoerg     // Is the function argument a pointer type?
14917330f729Sjoerg     if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) &&
14927330f729Sjoerg         !attrNonNullArgCheck(
14937330f729Sjoerg             S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL,
14947330f729Sjoerg             Ex->getSourceRange(),
14957330f729Sjoerg             getFunctionOrMethodParamRange(D, Idx.getASTIndex())))
14967330f729Sjoerg       continue;
14977330f729Sjoerg 
14987330f729Sjoerg     NonNullArgs.push_back(Idx);
14997330f729Sjoerg   }
15007330f729Sjoerg 
15017330f729Sjoerg   // If no arguments were specified to __attribute__((nonnull)) then all pointer
15027330f729Sjoerg   // arguments have a nonnull attribute; warn if there aren't any. Skip this
15037330f729Sjoerg   // check if the attribute came from a macro expansion or a template
15047330f729Sjoerg   // instantiation.
15057330f729Sjoerg   if (NonNullArgs.empty() && AL.getLoc().isFileID() &&
15067330f729Sjoerg       !S.inTemplateInstantiation()) {
15077330f729Sjoerg     bool AnyPointers = isFunctionOrMethodVariadic(D);
15087330f729Sjoerg     for (unsigned I = 0, E = getFunctionOrMethodNumParams(D);
15097330f729Sjoerg          I != E && !AnyPointers; ++I) {
15107330f729Sjoerg       QualType T = getFunctionOrMethodParamType(D, I);
15117330f729Sjoerg       if (T->isDependentType() || S.isValidPointerAttrType(T))
15127330f729Sjoerg         AnyPointers = true;
15137330f729Sjoerg     }
15147330f729Sjoerg 
15157330f729Sjoerg     if (!AnyPointers)
15167330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers);
15177330f729Sjoerg   }
15187330f729Sjoerg 
15197330f729Sjoerg   ParamIdx *Start = NonNullArgs.data();
15207330f729Sjoerg   unsigned Size = NonNullArgs.size();
15217330f729Sjoerg   llvm::array_pod_sort(Start, Start + Size);
15227330f729Sjoerg   D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, Start, Size));
15237330f729Sjoerg }
15247330f729Sjoerg 
handleNonNullAttrParameter(Sema & S,ParmVarDecl * D,const ParsedAttr & AL)15257330f729Sjoerg static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
15267330f729Sjoerg                                        const ParsedAttr &AL) {
15277330f729Sjoerg   if (AL.getNumArgs() > 0) {
15287330f729Sjoerg     if (D->getFunctionType()) {
15297330f729Sjoerg       handleNonNullAttr(S, D, AL);
15307330f729Sjoerg     } else {
15317330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
15327330f729Sjoerg         << D->getSourceRange();
15337330f729Sjoerg     }
15347330f729Sjoerg     return;
15357330f729Sjoerg   }
15367330f729Sjoerg 
15377330f729Sjoerg   // Is the argument a pointer type?
15387330f729Sjoerg   if (!attrNonNullArgCheck(S, D->getType(), AL, SourceRange(),
15397330f729Sjoerg                            D->getSourceRange()))
15407330f729Sjoerg     return;
15417330f729Sjoerg 
15427330f729Sjoerg   D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, nullptr, 0));
15437330f729Sjoerg }
15447330f729Sjoerg 
handleReturnsNonNullAttr(Sema & S,Decl * D,const ParsedAttr & AL)15457330f729Sjoerg static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
15467330f729Sjoerg   QualType ResultType = getFunctionOrMethodResultType(D);
15477330f729Sjoerg   SourceRange SR = getFunctionOrMethodResultSourceRange(D);
15487330f729Sjoerg   if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR,
15497330f729Sjoerg                            /* isReturnValue */ true))
15507330f729Sjoerg     return;
15517330f729Sjoerg 
15527330f729Sjoerg   D->addAttr(::new (S.Context) ReturnsNonNullAttr(S.Context, AL));
15537330f729Sjoerg }
15547330f729Sjoerg 
handleNoEscapeAttr(Sema & S,Decl * D,const ParsedAttr & AL)15557330f729Sjoerg static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
15567330f729Sjoerg   if (D->isInvalidDecl())
15577330f729Sjoerg     return;
15587330f729Sjoerg 
15597330f729Sjoerg   // noescape only applies to pointer types.
15607330f729Sjoerg   QualType T = cast<ParmVarDecl>(D)->getType();
15617330f729Sjoerg   if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) {
15627330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
15637330f729Sjoerg         << AL << AL.getRange() << 0;
15647330f729Sjoerg     return;
15657330f729Sjoerg   }
15667330f729Sjoerg 
15677330f729Sjoerg   D->addAttr(::new (S.Context) NoEscapeAttr(S.Context, AL));
15687330f729Sjoerg }
15697330f729Sjoerg 
handleAssumeAlignedAttr(Sema & S,Decl * D,const ParsedAttr & AL)15707330f729Sjoerg static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
15717330f729Sjoerg   Expr *E = AL.getArgAsExpr(0),
15727330f729Sjoerg        *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr;
15737330f729Sjoerg   S.AddAssumeAlignedAttr(D, AL, E, OE);
15747330f729Sjoerg }
15757330f729Sjoerg 
handleAllocAlignAttr(Sema & S,Decl * D,const ParsedAttr & AL)15767330f729Sjoerg static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
15777330f729Sjoerg   S.AddAllocAlignAttr(D, AL, AL.getArgAsExpr(0));
15787330f729Sjoerg }
15797330f729Sjoerg 
AddAssumeAlignedAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E,Expr * OE)15807330f729Sjoerg void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
15817330f729Sjoerg                                 Expr *OE) {
15827330f729Sjoerg   QualType ResultType = getFunctionOrMethodResultType(D);
15837330f729Sjoerg   SourceRange SR = getFunctionOrMethodResultSourceRange(D);
15847330f729Sjoerg 
15857330f729Sjoerg   AssumeAlignedAttr TmpAttr(Context, CI, E, OE);
15867330f729Sjoerg   SourceLocation AttrLoc = TmpAttr.getLocation();
15877330f729Sjoerg 
15887330f729Sjoerg   if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
15897330f729Sjoerg     Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
15907330f729Sjoerg         << &TmpAttr << TmpAttr.getRange() << SR;
15917330f729Sjoerg     return;
15927330f729Sjoerg   }
15937330f729Sjoerg 
15947330f729Sjoerg   if (!E->isValueDependent()) {
1595*e038c9c4Sjoerg     Optional<llvm::APSInt> I = llvm::APSInt(64);
1596*e038c9c4Sjoerg     if (!(I = E->getIntegerConstantExpr(Context))) {
15977330f729Sjoerg       if (OE)
15987330f729Sjoerg         Diag(AttrLoc, diag::err_attribute_argument_n_type)
15997330f729Sjoerg           << &TmpAttr << 1 << AANT_ArgumentIntegerConstant
16007330f729Sjoerg           << E->getSourceRange();
16017330f729Sjoerg       else
16027330f729Sjoerg         Diag(AttrLoc, diag::err_attribute_argument_type)
16037330f729Sjoerg           << &TmpAttr << AANT_ArgumentIntegerConstant
16047330f729Sjoerg           << E->getSourceRange();
16057330f729Sjoerg       return;
16067330f729Sjoerg     }
16077330f729Sjoerg 
1608*e038c9c4Sjoerg     if (!I->isPowerOf2()) {
16097330f729Sjoerg       Diag(AttrLoc, diag::err_alignment_not_power_of_two)
16107330f729Sjoerg         << E->getSourceRange();
16117330f729Sjoerg       return;
16127330f729Sjoerg     }
1613*e038c9c4Sjoerg 
1614*e038c9c4Sjoerg     if (*I > Sema::MaximumAlignment)
1615*e038c9c4Sjoerg       Diag(CI.getLoc(), diag::warn_assume_aligned_too_great)
1616*e038c9c4Sjoerg           << CI.getRange() << Sema::MaximumAlignment;
16177330f729Sjoerg   }
16187330f729Sjoerg 
1619*e038c9c4Sjoerg   if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) {
16207330f729Sjoerg     Diag(AttrLoc, diag::err_attribute_argument_n_type)
16217330f729Sjoerg         << &TmpAttr << 2 << AANT_ArgumentIntegerConstant
16227330f729Sjoerg         << OE->getSourceRange();
16237330f729Sjoerg     return;
16247330f729Sjoerg   }
16257330f729Sjoerg 
16267330f729Sjoerg   D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE));
16277330f729Sjoerg }
16287330f729Sjoerg 
AddAllocAlignAttr(Decl * D,const AttributeCommonInfo & CI,Expr * ParamExpr)16297330f729Sjoerg void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
16307330f729Sjoerg                              Expr *ParamExpr) {
16317330f729Sjoerg   QualType ResultType = getFunctionOrMethodResultType(D);
16327330f729Sjoerg 
16337330f729Sjoerg   AllocAlignAttr TmpAttr(Context, CI, ParamIdx());
16347330f729Sjoerg   SourceLocation AttrLoc = CI.getLoc();
16357330f729Sjoerg 
16367330f729Sjoerg   if (!ResultType->isDependentType() &&
16377330f729Sjoerg       !isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
16387330f729Sjoerg     Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
16397330f729Sjoerg         << &TmpAttr << CI.getRange() << getFunctionOrMethodResultSourceRange(D);
16407330f729Sjoerg     return;
16417330f729Sjoerg   }
16427330f729Sjoerg 
16437330f729Sjoerg   ParamIdx Idx;
16447330f729Sjoerg   const auto *FuncDecl = cast<FunctionDecl>(D);
16457330f729Sjoerg   if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr,
16467330f729Sjoerg                                            /*AttrArgNum=*/1, ParamExpr, Idx))
16477330f729Sjoerg     return;
16487330f729Sjoerg 
16497330f729Sjoerg   QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
1650*e038c9c4Sjoerg   if (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
1651*e038c9c4Sjoerg       !Ty->isAlignValT()) {
16527330f729Sjoerg     Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only)
16537330f729Sjoerg         << &TmpAttr
16547330f729Sjoerg         << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange();
16557330f729Sjoerg     return;
16567330f729Sjoerg   }
16577330f729Sjoerg 
16587330f729Sjoerg   D->addAttr(::new (Context) AllocAlignAttr(Context, CI, Idx));
16597330f729Sjoerg }
16607330f729Sjoerg 
1661*e038c9c4Sjoerg /// Check if \p AssumptionStr is a known assumption and warn if not.
checkAssumptionAttr(Sema & S,SourceLocation Loc,StringRef AssumptionStr)1662*e038c9c4Sjoerg static void checkAssumptionAttr(Sema &S, SourceLocation Loc,
1663*e038c9c4Sjoerg                                 StringRef AssumptionStr) {
1664*e038c9c4Sjoerg   if (llvm::KnownAssumptionStrings.count(AssumptionStr))
1665*e038c9c4Sjoerg     return;
1666*e038c9c4Sjoerg 
1667*e038c9c4Sjoerg   unsigned BestEditDistance = 3;
1668*e038c9c4Sjoerg   StringRef Suggestion;
1669*e038c9c4Sjoerg   for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
1670*e038c9c4Sjoerg     unsigned EditDistance =
1671*e038c9c4Sjoerg         AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
1672*e038c9c4Sjoerg     if (EditDistance < BestEditDistance) {
1673*e038c9c4Sjoerg       Suggestion = KnownAssumptionIt.getKey();
1674*e038c9c4Sjoerg       BestEditDistance = EditDistance;
1675*e038c9c4Sjoerg     }
1676*e038c9c4Sjoerg   }
1677*e038c9c4Sjoerg 
1678*e038c9c4Sjoerg   if (!Suggestion.empty())
1679*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_assume_attribute_string_unknown_suggested)
1680*e038c9c4Sjoerg         << AssumptionStr << Suggestion;
1681*e038c9c4Sjoerg   else
1682*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_assume_attribute_string_unknown) << AssumptionStr;
1683*e038c9c4Sjoerg }
1684*e038c9c4Sjoerg 
handleAssumumptionAttr(Sema & S,Decl * D,const ParsedAttr & AL)1685*e038c9c4Sjoerg static void handleAssumumptionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1686*e038c9c4Sjoerg   // Handle the case where the attribute has a text message.
1687*e038c9c4Sjoerg   StringRef Str;
1688*e038c9c4Sjoerg   SourceLocation AttrStrLoc;
1689*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
1690*e038c9c4Sjoerg     return;
1691*e038c9c4Sjoerg 
1692*e038c9c4Sjoerg   checkAssumptionAttr(S, AttrStrLoc, Str);
1693*e038c9c4Sjoerg 
1694*e038c9c4Sjoerg   D->addAttr(::new (S.Context) AssumptionAttr(S.Context, AL, Str));
1695*e038c9c4Sjoerg }
1696*e038c9c4Sjoerg 
16977330f729Sjoerg /// Normalize the attribute, __foo__ becomes foo.
16987330f729Sjoerg /// Returns true if normalization was applied.
normalizeName(StringRef & AttrName)16997330f729Sjoerg static bool normalizeName(StringRef &AttrName) {
17007330f729Sjoerg   if (AttrName.size() > 4 && AttrName.startswith("__") &&
17017330f729Sjoerg       AttrName.endswith("__")) {
17027330f729Sjoerg     AttrName = AttrName.drop_front(2).drop_back(2);
17037330f729Sjoerg     return true;
17047330f729Sjoerg   }
17057330f729Sjoerg   return false;
17067330f729Sjoerg }
17077330f729Sjoerg 
handleOwnershipAttr(Sema & S,Decl * D,const ParsedAttr & AL)17087330f729Sjoerg static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
17097330f729Sjoerg   // This attribute must be applied to a function declaration. The first
17107330f729Sjoerg   // argument to the attribute must be an identifier, the name of the resource,
17117330f729Sjoerg   // for example: malloc. The following arguments must be argument indexes, the
17127330f729Sjoerg   // arguments must be of integer type for Returns, otherwise of pointer type.
17137330f729Sjoerg   // The difference between Holds and Takes is that a pointer may still be used
17147330f729Sjoerg   // after being held. free() should be __attribute((ownership_takes)), whereas
17157330f729Sjoerg   // a list append function may well be __attribute((ownership_holds)).
17167330f729Sjoerg 
17177330f729Sjoerg   if (!AL.isArgIdent(0)) {
17187330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
17197330f729Sjoerg         << AL << 1 << AANT_ArgumentIdentifier;
17207330f729Sjoerg     return;
17217330f729Sjoerg   }
17227330f729Sjoerg 
17237330f729Sjoerg   // Figure out our Kind.
17247330f729Sjoerg   OwnershipAttr::OwnershipKind K =
17257330f729Sjoerg       OwnershipAttr(S.Context, AL, nullptr, nullptr, 0).getOwnKind();
17267330f729Sjoerg 
17277330f729Sjoerg   // Check arguments.
17287330f729Sjoerg   switch (K) {
17297330f729Sjoerg   case OwnershipAttr::Takes:
17307330f729Sjoerg   case OwnershipAttr::Holds:
17317330f729Sjoerg     if (AL.getNumArgs() < 2) {
17327330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL << 2;
17337330f729Sjoerg       return;
17347330f729Sjoerg     }
17357330f729Sjoerg     break;
17367330f729Sjoerg   case OwnershipAttr::Returns:
17377330f729Sjoerg     if (AL.getNumArgs() > 2) {
17387330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
17397330f729Sjoerg       return;
17407330f729Sjoerg     }
17417330f729Sjoerg     break;
17427330f729Sjoerg   }
17437330f729Sjoerg 
17447330f729Sjoerg   IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
17457330f729Sjoerg 
17467330f729Sjoerg   StringRef ModuleName = Module->getName();
17477330f729Sjoerg   if (normalizeName(ModuleName)) {
17487330f729Sjoerg     Module = &S.PP.getIdentifierTable().get(ModuleName);
17497330f729Sjoerg   }
17507330f729Sjoerg 
17517330f729Sjoerg   SmallVector<ParamIdx, 8> OwnershipArgs;
17527330f729Sjoerg   for (unsigned i = 1; i < AL.getNumArgs(); ++i) {
17537330f729Sjoerg     Expr *Ex = AL.getArgAsExpr(i);
17547330f729Sjoerg     ParamIdx Idx;
17557330f729Sjoerg     if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx))
17567330f729Sjoerg       return;
17577330f729Sjoerg 
17587330f729Sjoerg     // Is the function argument a pointer type?
17597330f729Sjoerg     QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex());
17607330f729Sjoerg     int Err = -1;  // No error
17617330f729Sjoerg     switch (K) {
17627330f729Sjoerg       case OwnershipAttr::Takes:
17637330f729Sjoerg       case OwnershipAttr::Holds:
17647330f729Sjoerg         if (!T->isAnyPointerType() && !T->isBlockPointerType())
17657330f729Sjoerg           Err = 0;
17667330f729Sjoerg         break;
17677330f729Sjoerg       case OwnershipAttr::Returns:
17687330f729Sjoerg         if (!T->isIntegerType())
17697330f729Sjoerg           Err = 1;
17707330f729Sjoerg         break;
17717330f729Sjoerg     }
17727330f729Sjoerg     if (-1 != Err) {
17737330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err
17747330f729Sjoerg                                                     << Ex->getSourceRange();
17757330f729Sjoerg       return;
17767330f729Sjoerg     }
17777330f729Sjoerg 
17787330f729Sjoerg     // Check we don't have a conflict with another ownership attribute.
17797330f729Sjoerg     for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
17807330f729Sjoerg       // Cannot have two ownership attributes of different kinds for the same
17817330f729Sjoerg       // index.
17827330f729Sjoerg       if (I->getOwnKind() != K && I->args_end() !=
17837330f729Sjoerg           std::find(I->args_begin(), I->args_end(), Idx)) {
17847330f729Sjoerg         S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I;
17857330f729Sjoerg         return;
17867330f729Sjoerg       } else if (K == OwnershipAttr::Returns &&
17877330f729Sjoerg                  I->getOwnKind() == OwnershipAttr::Returns) {
17887330f729Sjoerg         // A returns attribute conflicts with any other returns attribute using
17897330f729Sjoerg         // a different index.
17907330f729Sjoerg         if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) {
17917330f729Sjoerg           S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch)
17927330f729Sjoerg               << I->args_begin()->getSourceIndex();
17937330f729Sjoerg           if (I->args_size())
17947330f729Sjoerg             S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch)
17957330f729Sjoerg                 << Idx.getSourceIndex() << Ex->getSourceRange();
17967330f729Sjoerg           return;
17977330f729Sjoerg         }
17987330f729Sjoerg       }
17997330f729Sjoerg     }
18007330f729Sjoerg     OwnershipArgs.push_back(Idx);
18017330f729Sjoerg   }
18027330f729Sjoerg 
18037330f729Sjoerg   ParamIdx *Start = OwnershipArgs.data();
18047330f729Sjoerg   unsigned Size = OwnershipArgs.size();
18057330f729Sjoerg   llvm::array_pod_sort(Start, Start + Size);
18067330f729Sjoerg   D->addAttr(::new (S.Context)
18077330f729Sjoerg                  OwnershipAttr(S.Context, AL, Module, Start, Size));
18087330f729Sjoerg }
18097330f729Sjoerg 
handleWeakRefAttr(Sema & S,Decl * D,const ParsedAttr & AL)18107330f729Sjoerg static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
18117330f729Sjoerg   // Check the attribute arguments.
18127330f729Sjoerg   if (AL.getNumArgs() > 1) {
18137330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
18147330f729Sjoerg     return;
18157330f729Sjoerg   }
18167330f729Sjoerg 
18177330f729Sjoerg   // gcc rejects
18187330f729Sjoerg   // class c {
18197330f729Sjoerg   //   static int a __attribute__((weakref ("v2")));
18207330f729Sjoerg   //   static int b() __attribute__((weakref ("f3")));
18217330f729Sjoerg   // };
18227330f729Sjoerg   // and ignores the attributes of
18237330f729Sjoerg   // void f(void) {
18247330f729Sjoerg   //   static int a __attribute__((weakref ("v2")));
18257330f729Sjoerg   // }
18267330f729Sjoerg   // we reject them
18277330f729Sjoerg   const DeclContext *Ctx = D->getDeclContext()->getRedeclContext();
18287330f729Sjoerg   if (!Ctx->isFileContext()) {
18297330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_weakref_not_global_context)
18307330f729Sjoerg         << cast<NamedDecl>(D);
18317330f729Sjoerg     return;
18327330f729Sjoerg   }
18337330f729Sjoerg 
18347330f729Sjoerg   // The GCC manual says
18357330f729Sjoerg   //
18367330f729Sjoerg   // At present, a declaration to which `weakref' is attached can only
18377330f729Sjoerg   // be `static'.
18387330f729Sjoerg   //
18397330f729Sjoerg   // It also says
18407330f729Sjoerg   //
18417330f729Sjoerg   // Without a TARGET,
18427330f729Sjoerg   // given as an argument to `weakref' or to `alias', `weakref' is
18437330f729Sjoerg   // equivalent to `weak'.
18447330f729Sjoerg   //
18457330f729Sjoerg   // gcc 4.4.1 will accept
18467330f729Sjoerg   // int a7 __attribute__((weakref));
18477330f729Sjoerg   // as
18487330f729Sjoerg   // int a7 __attribute__((weak));
18497330f729Sjoerg   // This looks like a bug in gcc. We reject that for now. We should revisit
18507330f729Sjoerg   // it if this behaviour is actually used.
18517330f729Sjoerg 
18527330f729Sjoerg   // GCC rejects
18537330f729Sjoerg   // static ((alias ("y"), weakref)).
18547330f729Sjoerg   // Should we? How to check that weakref is before or after alias?
18557330f729Sjoerg 
18567330f729Sjoerg   // FIXME: it would be good for us to keep the WeakRefAttr as-written instead
18577330f729Sjoerg   // of transforming it into an AliasAttr.  The WeakRefAttr never uses the
18587330f729Sjoerg   // StringRef parameter it was given anyway.
18597330f729Sjoerg   StringRef Str;
18607330f729Sjoerg   if (AL.getNumArgs() && S.checkStringLiteralArgumentAttr(AL, 0, Str))
18617330f729Sjoerg     // GCC will accept anything as the argument of weakref. Should we
18627330f729Sjoerg     // check for an existing decl?
18637330f729Sjoerg     D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str));
18647330f729Sjoerg 
18657330f729Sjoerg   D->addAttr(::new (S.Context) WeakRefAttr(S.Context, AL));
18667330f729Sjoerg }
18677330f729Sjoerg 
handleIFuncAttr(Sema & S,Decl * D,const ParsedAttr & AL)18687330f729Sjoerg static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
18697330f729Sjoerg   StringRef Str;
18707330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
18717330f729Sjoerg     return;
18727330f729Sjoerg 
18737330f729Sjoerg   // Aliases should be on declarations, not definitions.
18747330f729Sjoerg   const auto *FD = cast<FunctionDecl>(D);
18757330f729Sjoerg   if (FD->isThisDeclarationADefinition()) {
18767330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 1;
18777330f729Sjoerg     return;
18787330f729Sjoerg   }
18797330f729Sjoerg 
18807330f729Sjoerg   D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str));
18817330f729Sjoerg }
18827330f729Sjoerg 
handleAliasAttr(Sema & S,Decl * D,const ParsedAttr & AL)18837330f729Sjoerg static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
18847330f729Sjoerg   StringRef Str;
18857330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
18867330f729Sjoerg     return;
18877330f729Sjoerg 
18887330f729Sjoerg   if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
18897330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin);
18907330f729Sjoerg     return;
18917330f729Sjoerg   }
18927330f729Sjoerg   if (S.Context.getTargetInfo().getTriple().isNVPTX()) {
18937330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_nvptx);
18947330f729Sjoerg   }
18957330f729Sjoerg 
18967330f729Sjoerg   // Aliases should be on declarations, not definitions.
18977330f729Sjoerg   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
18987330f729Sjoerg     if (FD->isThisDeclarationADefinition()) {
18997330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 0;
19007330f729Sjoerg       return;
19017330f729Sjoerg     }
19027330f729Sjoerg   } else {
19037330f729Sjoerg     const auto *VD = cast<VarDecl>(D);
19047330f729Sjoerg     if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) {
19057330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_alias_is_definition) << VD << 0;
19067330f729Sjoerg       return;
19077330f729Sjoerg     }
19087330f729Sjoerg   }
19097330f729Sjoerg 
19107330f729Sjoerg   // Mark target used to prevent unneeded-internal-declaration warnings.
19117330f729Sjoerg   if (!S.LangOpts.CPlusPlus) {
19127330f729Sjoerg     // FIXME: demangle Str for C++, as the attribute refers to the mangled
19137330f729Sjoerg     // linkage name, not the pre-mangled identifier.
19147330f729Sjoerg     const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc());
19157330f729Sjoerg     LookupResult LR(S, target, Sema::LookupOrdinaryName);
19167330f729Sjoerg     if (S.LookupQualifiedName(LR, S.getCurLexicalContext()))
19177330f729Sjoerg       for (NamedDecl *ND : LR)
19187330f729Sjoerg         ND->markUsed(S.Context);
19197330f729Sjoerg   }
19207330f729Sjoerg 
19217330f729Sjoerg   D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str));
19227330f729Sjoerg }
19237330f729Sjoerg 
handleTLSModelAttr(Sema & S,Decl * D,const ParsedAttr & AL)19247330f729Sjoerg static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
19257330f729Sjoerg   StringRef Model;
19267330f729Sjoerg   SourceLocation LiteralLoc;
19277330f729Sjoerg   // Check that it is a string.
19287330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc))
19297330f729Sjoerg     return;
19307330f729Sjoerg 
19317330f729Sjoerg   // Check that the value.
19327330f729Sjoerg   if (Model != "global-dynamic" && Model != "local-dynamic"
19337330f729Sjoerg       && Model != "initial-exec" && Model != "local-exec") {
19347330f729Sjoerg     S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg);
19357330f729Sjoerg     return;
19367330f729Sjoerg   }
19377330f729Sjoerg 
1938*e038c9c4Sjoerg   if (S.Context.getTargetInfo().getTriple().isOSAIX() &&
1939*e038c9c4Sjoerg       Model != "global-dynamic") {
1940*e038c9c4Sjoerg     S.Diag(LiteralLoc, diag::err_aix_attr_unsupported_tls_model) << Model;
1941*e038c9c4Sjoerg     return;
1942*e038c9c4Sjoerg   }
1943*e038c9c4Sjoerg 
19447330f729Sjoerg   D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model));
19457330f729Sjoerg }
19467330f729Sjoerg 
handleRestrictAttr(Sema & S,Decl * D,const ParsedAttr & AL)19477330f729Sjoerg static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
19487330f729Sjoerg   QualType ResultType = getFunctionOrMethodResultType(D);
19497330f729Sjoerg   if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) {
19507330f729Sjoerg     D->addAttr(::new (S.Context) RestrictAttr(S.Context, AL));
19517330f729Sjoerg     return;
19527330f729Sjoerg   }
19537330f729Sjoerg 
19547330f729Sjoerg   S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
19557330f729Sjoerg       << AL << getFunctionOrMethodResultSourceRange(D);
19567330f729Sjoerg }
19577330f729Sjoerg 
handleCPUSpecificAttr(Sema & S,Decl * D,const ParsedAttr & AL)19587330f729Sjoerg static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
19597330f729Sjoerg   FunctionDecl *FD = cast<FunctionDecl>(D);
19607330f729Sjoerg 
19617330f729Sjoerg   if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
19627330f729Sjoerg     if (MD->getParent()->isLambda()) {
19637330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_dll_lambda) << AL;
19647330f729Sjoerg       return;
19657330f729Sjoerg     }
19667330f729Sjoerg   }
19677330f729Sjoerg 
1968*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1))
19697330f729Sjoerg     return;
19707330f729Sjoerg 
19717330f729Sjoerg   SmallVector<IdentifierInfo *, 8> CPUs;
19727330f729Sjoerg   for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) {
19737330f729Sjoerg     if (!AL.isArgIdent(ArgNo)) {
19747330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
19757330f729Sjoerg           << AL << AANT_ArgumentIdentifier;
19767330f729Sjoerg       return;
19777330f729Sjoerg     }
19787330f729Sjoerg 
19797330f729Sjoerg     IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo);
19807330f729Sjoerg     StringRef CPUName = CPUArg->Ident->getName().trim();
19817330f729Sjoerg 
19827330f729Sjoerg     if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) {
19837330f729Sjoerg       S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value)
19847330f729Sjoerg           << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch);
19857330f729Sjoerg       return;
19867330f729Sjoerg     }
19877330f729Sjoerg 
19887330f729Sjoerg     const TargetInfo &Target = S.Context.getTargetInfo();
19897330f729Sjoerg     if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) {
19907330f729Sjoerg           return Target.CPUSpecificManglingCharacter(CPUName) ==
19917330f729Sjoerg                  Target.CPUSpecificManglingCharacter(Cur->getName());
19927330f729Sjoerg         })) {
19937330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries);
19947330f729Sjoerg       return;
19957330f729Sjoerg     }
19967330f729Sjoerg     CPUs.push_back(CPUArg->Ident);
19977330f729Sjoerg   }
19987330f729Sjoerg 
19997330f729Sjoerg   FD->setIsMultiVersion(true);
20007330f729Sjoerg   if (AL.getKind() == ParsedAttr::AT_CPUSpecific)
20017330f729Sjoerg     D->addAttr(::new (S.Context)
20027330f729Sjoerg                    CPUSpecificAttr(S.Context, AL, CPUs.data(), CPUs.size()));
20037330f729Sjoerg   else
20047330f729Sjoerg     D->addAttr(::new (S.Context)
20057330f729Sjoerg                    CPUDispatchAttr(S.Context, AL, CPUs.data(), CPUs.size()));
20067330f729Sjoerg }
20077330f729Sjoerg 
handleCommonAttr(Sema & S,Decl * D,const ParsedAttr & AL)20087330f729Sjoerg static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20097330f729Sjoerg   if (S.LangOpts.CPlusPlus) {
20107330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
20117330f729Sjoerg         << AL << AttributeLangSupport::Cpp;
20127330f729Sjoerg     return;
20137330f729Sjoerg   }
20147330f729Sjoerg 
2015*e038c9c4Sjoerg   D->addAttr(::new (S.Context) CommonAttr(S.Context, AL));
2016*e038c9c4Sjoerg }
2017*e038c9c4Sjoerg 
handleCmseNSEntryAttr(Sema & S,Decl * D,const ParsedAttr & AL)2018*e038c9c4Sjoerg static void handleCmseNSEntryAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
2019*e038c9c4Sjoerg   if (S.LangOpts.CPlusPlus && !D->getDeclContext()->isExternCContext()) {
2020*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
2021*e038c9c4Sjoerg     return;
2022*e038c9c4Sjoerg   }
2023*e038c9c4Sjoerg 
2024*e038c9c4Sjoerg   const auto *FD = cast<FunctionDecl>(D);
2025*e038c9c4Sjoerg   if (!FD->isExternallyVisible()) {
2026*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
2027*e038c9c4Sjoerg     return;
2028*e038c9c4Sjoerg   }
2029*e038c9c4Sjoerg 
2030*e038c9c4Sjoerg   D->addAttr(::new (S.Context) CmseNSEntryAttr(S.Context, AL));
20317330f729Sjoerg }
20327330f729Sjoerg 
handleNakedAttr(Sema & S,Decl * D,const ParsedAttr & AL)20337330f729Sjoerg static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20347330f729Sjoerg   if (AL.isDeclspecAttribute()) {
20357330f729Sjoerg     const auto &Triple = S.getASTContext().getTargetInfo().getTriple();
20367330f729Sjoerg     const auto &Arch = Triple.getArch();
20377330f729Sjoerg     if (Arch != llvm::Triple::x86 &&
20387330f729Sjoerg         (Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) {
20397330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch)
20407330f729Sjoerg           << AL << Triple.getArchName();
20417330f729Sjoerg       return;
20427330f729Sjoerg     }
20437330f729Sjoerg   }
20447330f729Sjoerg 
20457330f729Sjoerg   D->addAttr(::new (S.Context) NakedAttr(S.Context, AL));
20467330f729Sjoerg }
20477330f729Sjoerg 
handleNoReturnAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)20487330f729Sjoerg static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
20497330f729Sjoerg   if (hasDeclarator(D)) return;
20507330f729Sjoerg 
20517330f729Sjoerg   if (!isa<ObjCMethodDecl>(D)) {
20527330f729Sjoerg     S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
20537330f729Sjoerg         << Attrs << ExpectedFunctionOrMethod;
20547330f729Sjoerg     return;
20557330f729Sjoerg   }
20567330f729Sjoerg 
20577330f729Sjoerg   D->addAttr(::new (S.Context) NoReturnAttr(S.Context, Attrs));
20587330f729Sjoerg }
20597330f729Sjoerg 
handleNoCfCheckAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)20607330f729Sjoerg static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
20617330f729Sjoerg   if (!S.getLangOpts().CFProtectionBranch)
20627330f729Sjoerg     S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored);
20637330f729Sjoerg   else
20647330f729Sjoerg     handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs);
20657330f729Sjoerg }
20667330f729Sjoerg 
CheckAttrNoArgs(const ParsedAttr & Attrs)20677330f729Sjoerg bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) {
2068*e038c9c4Sjoerg   if (!Attrs.checkExactlyNumArgs(*this, 0)) {
20697330f729Sjoerg     Attrs.setInvalid();
20707330f729Sjoerg     return true;
20717330f729Sjoerg   }
20727330f729Sjoerg 
20737330f729Sjoerg   return false;
20747330f729Sjoerg }
20757330f729Sjoerg 
CheckAttrTarget(const ParsedAttr & AL)20767330f729Sjoerg bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
20777330f729Sjoerg   // Check whether the attribute is valid on the current target.
20787330f729Sjoerg   if (!AL.existsInTarget(Context.getTargetInfo())) {
2079*e038c9c4Sjoerg     Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
2080*e038c9c4Sjoerg         << AL << AL.getRange();
20817330f729Sjoerg     AL.setInvalid();
20827330f729Sjoerg     return true;
20837330f729Sjoerg   }
20847330f729Sjoerg 
20857330f729Sjoerg   return false;
20867330f729Sjoerg }
20877330f729Sjoerg 
handleAnalyzerNoReturnAttr(Sema & S,Decl * D,const ParsedAttr & AL)20887330f729Sjoerg static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20897330f729Sjoerg 
20907330f729Sjoerg   // The checking path for 'noreturn' and 'analyzer_noreturn' are different
20917330f729Sjoerg   // because 'analyzer_noreturn' does not impact the type.
20927330f729Sjoerg   if (!isFunctionOrMethodOrBlock(D)) {
20937330f729Sjoerg     ValueDecl *VD = dyn_cast<ValueDecl>(D);
20947330f729Sjoerg     if (!VD || (!VD->getType()->isBlockPointerType() &&
20957330f729Sjoerg                 !VD->getType()->isFunctionPointerType())) {
20967330f729Sjoerg       S.Diag(AL.getLoc(), AL.isCXX11Attribute()
20977330f729Sjoerg                               ? diag::err_attribute_wrong_decl_type
20987330f729Sjoerg                               : diag::warn_attribute_wrong_decl_type)
20997330f729Sjoerg           << AL << ExpectedFunctionMethodOrBlock;
21007330f729Sjoerg       return;
21017330f729Sjoerg     }
21027330f729Sjoerg   }
21037330f729Sjoerg 
21047330f729Sjoerg   D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(S.Context, AL));
21057330f729Sjoerg }
21067330f729Sjoerg 
21077330f729Sjoerg // PS3 PPU-specific.
handleVecReturnAttr(Sema & S,Decl * D,const ParsedAttr & AL)21087330f729Sjoerg static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
21097330f729Sjoerg   /*
21107330f729Sjoerg     Returning a Vector Class in Registers
21117330f729Sjoerg 
21127330f729Sjoerg     According to the PPU ABI specifications, a class with a single member of
21137330f729Sjoerg     vector type is returned in memory when used as the return value of a
21147330f729Sjoerg     function.
21157330f729Sjoerg     This results in inefficient code when implementing vector classes. To return
21167330f729Sjoerg     the value in a single vector register, add the vecreturn attribute to the
21177330f729Sjoerg     class definition. This attribute is also applicable to struct types.
21187330f729Sjoerg 
21197330f729Sjoerg     Example:
21207330f729Sjoerg 
21217330f729Sjoerg     struct Vector
21227330f729Sjoerg     {
21237330f729Sjoerg       __vector float xyzw;
21247330f729Sjoerg     } __attribute__((vecreturn));
21257330f729Sjoerg 
21267330f729Sjoerg     Vector Add(Vector lhs, Vector rhs)
21277330f729Sjoerg     {
21287330f729Sjoerg       Vector result;
21297330f729Sjoerg       result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
21307330f729Sjoerg       return result; // This will be returned in a register
21317330f729Sjoerg     }
21327330f729Sjoerg   */
21337330f729Sjoerg   if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
21347330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A;
21357330f729Sjoerg     return;
21367330f729Sjoerg   }
21377330f729Sjoerg 
21387330f729Sjoerg   const auto *R = cast<RecordDecl>(D);
21397330f729Sjoerg   int count = 0;
21407330f729Sjoerg 
21417330f729Sjoerg   if (!isa<CXXRecordDecl>(R)) {
21427330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
21437330f729Sjoerg     return;
21447330f729Sjoerg   }
21457330f729Sjoerg 
21467330f729Sjoerg   if (!cast<CXXRecordDecl>(R)->isPOD()) {
21477330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
21487330f729Sjoerg     return;
21497330f729Sjoerg   }
21507330f729Sjoerg 
21517330f729Sjoerg   for (const auto *I : R->fields()) {
21527330f729Sjoerg     if ((count == 1) || !I->getType()->isVectorType()) {
21537330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
21547330f729Sjoerg       return;
21557330f729Sjoerg     }
21567330f729Sjoerg     count++;
21577330f729Sjoerg   }
21587330f729Sjoerg 
21597330f729Sjoerg   D->addAttr(::new (S.Context) VecReturnAttr(S.Context, AL));
21607330f729Sjoerg }
21617330f729Sjoerg 
handleDependencyAttr(Sema & S,Scope * Scope,Decl * D,const ParsedAttr & AL)21627330f729Sjoerg static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
21637330f729Sjoerg                                  const ParsedAttr &AL) {
21647330f729Sjoerg   if (isa<ParmVarDecl>(D)) {
21657330f729Sjoerg     // [[carries_dependency]] can only be applied to a parameter if it is a
21667330f729Sjoerg     // parameter of a function declaration or lambda.
21677330f729Sjoerg     if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) {
21687330f729Sjoerg       S.Diag(AL.getLoc(),
21697330f729Sjoerg              diag::err_carries_dependency_param_not_function_decl);
21707330f729Sjoerg       return;
21717330f729Sjoerg     }
21727330f729Sjoerg   }
21737330f729Sjoerg 
21747330f729Sjoerg   D->addAttr(::new (S.Context) CarriesDependencyAttr(S.Context, AL));
21757330f729Sjoerg }
21767330f729Sjoerg 
handleUnusedAttr(Sema & S,Decl * D,const ParsedAttr & AL)21777330f729Sjoerg static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
21787330f729Sjoerg   bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName();
21797330f729Sjoerg 
21807330f729Sjoerg   // If this is spelled as the standard C++17 attribute, but not in C++17, warn
21817330f729Sjoerg   // about using it as an extension.
21827330f729Sjoerg   if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr)
21837330f729Sjoerg     S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
21847330f729Sjoerg 
21857330f729Sjoerg   D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL));
21867330f729Sjoerg }
21877330f729Sjoerg 
handleConstructorAttr(Sema & S,Decl * D,const ParsedAttr & AL)21887330f729Sjoerg static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
21897330f729Sjoerg   uint32_t priority = ConstructorAttr::DefaultPriority;
21907330f729Sjoerg   if (AL.getNumArgs() &&
21917330f729Sjoerg       !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
21927330f729Sjoerg     return;
21937330f729Sjoerg 
21947330f729Sjoerg   D->addAttr(::new (S.Context) ConstructorAttr(S.Context, AL, priority));
21957330f729Sjoerg }
21967330f729Sjoerg 
handleDestructorAttr(Sema & S,Decl * D,const ParsedAttr & AL)21977330f729Sjoerg static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
21987330f729Sjoerg   uint32_t priority = DestructorAttr::DefaultPriority;
21997330f729Sjoerg   if (AL.getNumArgs() &&
22007330f729Sjoerg       !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
22017330f729Sjoerg     return;
22027330f729Sjoerg 
22037330f729Sjoerg   D->addAttr(::new (S.Context) DestructorAttr(S.Context, AL, priority));
22047330f729Sjoerg }
22057330f729Sjoerg 
22067330f729Sjoerg template <typename AttrTy>
handleAttrWithMessage(Sema & S,Decl * D,const ParsedAttr & AL)22077330f729Sjoerg static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) {
22087330f729Sjoerg   // Handle the case where the attribute has a text message.
22097330f729Sjoerg   StringRef Str;
22107330f729Sjoerg   if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str))
22117330f729Sjoerg     return;
22127330f729Sjoerg 
22137330f729Sjoerg   D->addAttr(::new (S.Context) AttrTy(S.Context, AL, Str));
22147330f729Sjoerg }
22157330f729Sjoerg 
handleObjCSuppresProtocolAttr(Sema & S,Decl * D,const ParsedAttr & AL)22167330f729Sjoerg static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
22177330f729Sjoerg                                           const ParsedAttr &AL) {
22187330f729Sjoerg   if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
22197330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)
22207330f729Sjoerg         << AL << AL.getRange();
22217330f729Sjoerg     return;
22227330f729Sjoerg   }
22237330f729Sjoerg 
22247330f729Sjoerg   D->addAttr(::new (S.Context) ObjCExplicitProtocolImplAttr(S.Context, AL));
22257330f729Sjoerg }
22267330f729Sjoerg 
checkAvailabilityAttr(Sema & S,SourceRange Range,IdentifierInfo * Platform,VersionTuple Introduced,VersionTuple Deprecated,VersionTuple Obsoleted)22277330f729Sjoerg static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
22287330f729Sjoerg                                   IdentifierInfo *Platform,
22297330f729Sjoerg                                   VersionTuple Introduced,
22307330f729Sjoerg                                   VersionTuple Deprecated,
22317330f729Sjoerg                                   VersionTuple Obsoleted) {
22327330f729Sjoerg   StringRef PlatformName
22337330f729Sjoerg     = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
22347330f729Sjoerg   if (PlatformName.empty())
22357330f729Sjoerg     PlatformName = Platform->getName();
22367330f729Sjoerg 
22377330f729Sjoerg   // Ensure that Introduced <= Deprecated <= Obsoleted (although not all
22387330f729Sjoerg   // of these steps are needed).
22397330f729Sjoerg   if (!Introduced.empty() && !Deprecated.empty() &&
22407330f729Sjoerg       !(Introduced <= Deprecated)) {
22417330f729Sjoerg     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
22427330f729Sjoerg       << 1 << PlatformName << Deprecated.getAsString()
22437330f729Sjoerg       << 0 << Introduced.getAsString();
22447330f729Sjoerg     return true;
22457330f729Sjoerg   }
22467330f729Sjoerg 
22477330f729Sjoerg   if (!Introduced.empty() && !Obsoleted.empty() &&
22487330f729Sjoerg       !(Introduced <= Obsoleted)) {
22497330f729Sjoerg     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
22507330f729Sjoerg       << 2 << PlatformName << Obsoleted.getAsString()
22517330f729Sjoerg       << 0 << Introduced.getAsString();
22527330f729Sjoerg     return true;
22537330f729Sjoerg   }
22547330f729Sjoerg 
22557330f729Sjoerg   if (!Deprecated.empty() && !Obsoleted.empty() &&
22567330f729Sjoerg       !(Deprecated <= Obsoleted)) {
22577330f729Sjoerg     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
22587330f729Sjoerg       << 2 << PlatformName << Obsoleted.getAsString()
22597330f729Sjoerg       << 1 << Deprecated.getAsString();
22607330f729Sjoerg     return true;
22617330f729Sjoerg   }
22627330f729Sjoerg 
22637330f729Sjoerg   return false;
22647330f729Sjoerg }
22657330f729Sjoerg 
22667330f729Sjoerg /// Check whether the two versions match.
22677330f729Sjoerg ///
22687330f729Sjoerg /// If either version tuple is empty, then they are assumed to match. If
22697330f729Sjoerg /// \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)22707330f729Sjoerg static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y,
22717330f729Sjoerg                           bool BeforeIsOkay) {
22727330f729Sjoerg   if (X.empty() || Y.empty())
22737330f729Sjoerg     return true;
22747330f729Sjoerg 
22757330f729Sjoerg   if (X == Y)
22767330f729Sjoerg     return true;
22777330f729Sjoerg 
22787330f729Sjoerg   if (BeforeIsOkay && X < Y)
22797330f729Sjoerg     return true;
22807330f729Sjoerg 
22817330f729Sjoerg   return false;
22827330f729Sjoerg }
22837330f729Sjoerg 
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)22847330f729Sjoerg AvailabilityAttr *Sema::mergeAvailabilityAttr(
22857330f729Sjoerg     NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform,
22867330f729Sjoerg     bool Implicit, VersionTuple Introduced, VersionTuple Deprecated,
22877330f729Sjoerg     VersionTuple Obsoleted, bool IsUnavailable, StringRef Message,
22887330f729Sjoerg     bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK,
22897330f729Sjoerg     int Priority) {
22907330f729Sjoerg   VersionTuple MergedIntroduced = Introduced;
22917330f729Sjoerg   VersionTuple MergedDeprecated = Deprecated;
22927330f729Sjoerg   VersionTuple MergedObsoleted = Obsoleted;
22937330f729Sjoerg   bool FoundAny = false;
22947330f729Sjoerg   bool OverrideOrImpl = false;
22957330f729Sjoerg   switch (AMK) {
22967330f729Sjoerg   case AMK_None:
22977330f729Sjoerg   case AMK_Redeclaration:
22987330f729Sjoerg     OverrideOrImpl = false;
22997330f729Sjoerg     break;
23007330f729Sjoerg 
23017330f729Sjoerg   case AMK_Override:
23027330f729Sjoerg   case AMK_ProtocolImplementation:
2303*e038c9c4Sjoerg   case AMK_OptionalProtocolImplementation:
23047330f729Sjoerg     OverrideOrImpl = true;
23057330f729Sjoerg     break;
23067330f729Sjoerg   }
23077330f729Sjoerg 
23087330f729Sjoerg   if (D->hasAttrs()) {
23097330f729Sjoerg     AttrVec &Attrs = D->getAttrs();
23107330f729Sjoerg     for (unsigned i = 0, e = Attrs.size(); i != e;) {
23117330f729Sjoerg       const auto *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
23127330f729Sjoerg       if (!OldAA) {
23137330f729Sjoerg         ++i;
23147330f729Sjoerg         continue;
23157330f729Sjoerg       }
23167330f729Sjoerg 
23177330f729Sjoerg       IdentifierInfo *OldPlatform = OldAA->getPlatform();
23187330f729Sjoerg       if (OldPlatform != Platform) {
23197330f729Sjoerg         ++i;
23207330f729Sjoerg         continue;
23217330f729Sjoerg       }
23227330f729Sjoerg 
23237330f729Sjoerg       // If there is an existing availability attribute for this platform that
23247330f729Sjoerg       // has a lower priority use the existing one and discard the new
23257330f729Sjoerg       // attribute.
23267330f729Sjoerg       if (OldAA->getPriority() < Priority)
23277330f729Sjoerg         return nullptr;
23287330f729Sjoerg 
23297330f729Sjoerg       // If there is an existing attribute for this platform that has a higher
23307330f729Sjoerg       // priority than the new attribute then erase the old one and continue
23317330f729Sjoerg       // processing the attributes.
23327330f729Sjoerg       if (OldAA->getPriority() > Priority) {
23337330f729Sjoerg         Attrs.erase(Attrs.begin() + i);
23347330f729Sjoerg         --e;
23357330f729Sjoerg         continue;
23367330f729Sjoerg       }
23377330f729Sjoerg 
23387330f729Sjoerg       FoundAny = true;
23397330f729Sjoerg       VersionTuple OldIntroduced = OldAA->getIntroduced();
23407330f729Sjoerg       VersionTuple OldDeprecated = OldAA->getDeprecated();
23417330f729Sjoerg       VersionTuple OldObsoleted = OldAA->getObsoleted();
23427330f729Sjoerg       bool OldIsUnavailable = OldAA->getUnavailable();
23437330f729Sjoerg 
23447330f729Sjoerg       if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) ||
23457330f729Sjoerg           !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) ||
23467330f729Sjoerg           !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) ||
23477330f729Sjoerg           !(OldIsUnavailable == IsUnavailable ||
23487330f729Sjoerg             (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) {
23497330f729Sjoerg         if (OverrideOrImpl) {
23507330f729Sjoerg           int Which = -1;
23517330f729Sjoerg           VersionTuple FirstVersion;
23527330f729Sjoerg           VersionTuple SecondVersion;
23537330f729Sjoerg           if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) {
23547330f729Sjoerg             Which = 0;
23557330f729Sjoerg             FirstVersion = OldIntroduced;
23567330f729Sjoerg             SecondVersion = Introduced;
23577330f729Sjoerg           } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) {
23587330f729Sjoerg             Which = 1;
23597330f729Sjoerg             FirstVersion = Deprecated;
23607330f729Sjoerg             SecondVersion = OldDeprecated;
23617330f729Sjoerg           } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) {
23627330f729Sjoerg             Which = 2;
23637330f729Sjoerg             FirstVersion = Obsoleted;
23647330f729Sjoerg             SecondVersion = OldObsoleted;
23657330f729Sjoerg           }
23667330f729Sjoerg 
23677330f729Sjoerg           if (Which == -1) {
23687330f729Sjoerg             Diag(OldAA->getLocation(),
23697330f729Sjoerg                  diag::warn_mismatched_availability_override_unavail)
23707330f729Sjoerg               << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
23717330f729Sjoerg               << (AMK == AMK_Override);
2372*e038c9c4Sjoerg           } else if (Which != 1 && AMK == AMK_OptionalProtocolImplementation) {
2373*e038c9c4Sjoerg             // Allow different 'introduced' / 'obsoleted' availability versions
2374*e038c9c4Sjoerg             // on a method that implements an optional protocol requirement. It
2375*e038c9c4Sjoerg             // makes less sense to allow this for 'deprecated' as the user can't
2376*e038c9c4Sjoerg             // see if the method is 'deprecated' as 'respondsToSelector' will
2377*e038c9c4Sjoerg             // still return true when the method is deprecated.
2378*e038c9c4Sjoerg             ++i;
2379*e038c9c4Sjoerg             continue;
23807330f729Sjoerg           } else {
23817330f729Sjoerg             Diag(OldAA->getLocation(),
23827330f729Sjoerg                  diag::warn_mismatched_availability_override)
23837330f729Sjoerg               << Which
23847330f729Sjoerg               << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
23857330f729Sjoerg               << FirstVersion.getAsString() << SecondVersion.getAsString()
23867330f729Sjoerg               << (AMK == AMK_Override);
23877330f729Sjoerg           }
23887330f729Sjoerg           if (AMK == AMK_Override)
23897330f729Sjoerg             Diag(CI.getLoc(), diag::note_overridden_method);
23907330f729Sjoerg           else
23917330f729Sjoerg             Diag(CI.getLoc(), diag::note_protocol_method);
23927330f729Sjoerg         } else {
23937330f729Sjoerg           Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
23947330f729Sjoerg           Diag(CI.getLoc(), diag::note_previous_attribute);
23957330f729Sjoerg         }
23967330f729Sjoerg 
23977330f729Sjoerg         Attrs.erase(Attrs.begin() + i);
23987330f729Sjoerg         --e;
23997330f729Sjoerg         continue;
24007330f729Sjoerg       }
24017330f729Sjoerg 
24027330f729Sjoerg       VersionTuple MergedIntroduced2 = MergedIntroduced;
24037330f729Sjoerg       VersionTuple MergedDeprecated2 = MergedDeprecated;
24047330f729Sjoerg       VersionTuple MergedObsoleted2 = MergedObsoleted;
24057330f729Sjoerg 
24067330f729Sjoerg       if (MergedIntroduced2.empty())
24077330f729Sjoerg         MergedIntroduced2 = OldIntroduced;
24087330f729Sjoerg       if (MergedDeprecated2.empty())
24097330f729Sjoerg         MergedDeprecated2 = OldDeprecated;
24107330f729Sjoerg       if (MergedObsoleted2.empty())
24117330f729Sjoerg         MergedObsoleted2 = OldObsoleted;
24127330f729Sjoerg 
24137330f729Sjoerg       if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform,
24147330f729Sjoerg                                 MergedIntroduced2, MergedDeprecated2,
24157330f729Sjoerg                                 MergedObsoleted2)) {
24167330f729Sjoerg         Attrs.erase(Attrs.begin() + i);
24177330f729Sjoerg         --e;
24187330f729Sjoerg         continue;
24197330f729Sjoerg       }
24207330f729Sjoerg 
24217330f729Sjoerg       MergedIntroduced = MergedIntroduced2;
24227330f729Sjoerg       MergedDeprecated = MergedDeprecated2;
24237330f729Sjoerg       MergedObsoleted = MergedObsoleted2;
24247330f729Sjoerg       ++i;
24257330f729Sjoerg     }
24267330f729Sjoerg   }
24277330f729Sjoerg 
24287330f729Sjoerg   if (FoundAny &&
24297330f729Sjoerg       MergedIntroduced == Introduced &&
24307330f729Sjoerg       MergedDeprecated == Deprecated &&
24317330f729Sjoerg       MergedObsoleted == Obsoleted)
24327330f729Sjoerg     return nullptr;
24337330f729Sjoerg 
24347330f729Sjoerg   // Only create a new attribute if !OverrideOrImpl, but we want to do
24357330f729Sjoerg   // the checking.
24367330f729Sjoerg   if (!checkAvailabilityAttr(*this, CI.getRange(), Platform, MergedIntroduced,
24377330f729Sjoerg                              MergedDeprecated, MergedObsoleted) &&
24387330f729Sjoerg       !OverrideOrImpl) {
24397330f729Sjoerg     auto *Avail = ::new (Context) AvailabilityAttr(
24407330f729Sjoerg         Context, CI, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable,
24417330f729Sjoerg         Message, IsStrict, Replacement, Priority);
24427330f729Sjoerg     Avail->setImplicit(Implicit);
24437330f729Sjoerg     return Avail;
24447330f729Sjoerg   }
24457330f729Sjoerg   return nullptr;
24467330f729Sjoerg }
24477330f729Sjoerg 
handleAvailabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)24487330f729Sjoerg static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
2449*e038c9c4Sjoerg   if (!AL.checkExactlyNumArgs(S, 1))
24507330f729Sjoerg     return;
24517330f729Sjoerg   IdentifierLoc *Platform = AL.getArgAsIdent(0);
24527330f729Sjoerg 
24537330f729Sjoerg   IdentifierInfo *II = Platform->Ident;
24547330f729Sjoerg   if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
24557330f729Sjoerg     S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
24567330f729Sjoerg       << Platform->Ident;
24577330f729Sjoerg 
24587330f729Sjoerg   auto *ND = dyn_cast<NamedDecl>(D);
24597330f729Sjoerg   if (!ND) // We warned about this already, so just return.
24607330f729Sjoerg     return;
24617330f729Sjoerg 
24627330f729Sjoerg   AvailabilityChange Introduced = AL.getAvailabilityIntroduced();
24637330f729Sjoerg   AvailabilityChange Deprecated = AL.getAvailabilityDeprecated();
24647330f729Sjoerg   AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted();
24657330f729Sjoerg   bool IsUnavailable = AL.getUnavailableLoc().isValid();
24667330f729Sjoerg   bool IsStrict = AL.getStrictLoc().isValid();
24677330f729Sjoerg   StringRef Str;
24687330f729Sjoerg   if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getMessageExpr()))
24697330f729Sjoerg     Str = SE->getString();
24707330f729Sjoerg   StringRef Replacement;
24717330f729Sjoerg   if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr()))
24727330f729Sjoerg     Replacement = SE->getString();
24737330f729Sjoerg 
24747330f729Sjoerg   if (II->isStr("swift")) {
24757330f729Sjoerg     if (Introduced.isValid() || Obsoleted.isValid() ||
24767330f729Sjoerg         (!IsUnavailable && !Deprecated.isValid())) {
24777330f729Sjoerg       S.Diag(AL.getLoc(),
24787330f729Sjoerg              diag::warn_availability_swift_unavailable_deprecated_only);
24797330f729Sjoerg       return;
24807330f729Sjoerg     }
24817330f729Sjoerg   }
24827330f729Sjoerg 
24837330f729Sjoerg   int PriorityModifier = AL.isPragmaClangAttribute()
24847330f729Sjoerg                              ? Sema::AP_PragmaClangAttribute
24857330f729Sjoerg                              : Sema::AP_Explicit;
24867330f729Sjoerg   AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
24877330f729Sjoerg       ND, AL, II, false /*Implicit*/, Introduced.Version, Deprecated.Version,
24887330f729Sjoerg       Obsoleted.Version, IsUnavailable, Str, IsStrict, Replacement,
24897330f729Sjoerg       Sema::AMK_None, PriorityModifier);
24907330f729Sjoerg   if (NewAttr)
24917330f729Sjoerg     D->addAttr(NewAttr);
24927330f729Sjoerg 
24937330f729Sjoerg   // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning
24947330f729Sjoerg   // matches before the start of the watchOS platform.
24957330f729Sjoerg   if (S.Context.getTargetInfo().getTriple().isWatchOS()) {
24967330f729Sjoerg     IdentifierInfo *NewII = nullptr;
24977330f729Sjoerg     if (II->getName() == "ios")
24987330f729Sjoerg       NewII = &S.Context.Idents.get("watchos");
24997330f729Sjoerg     else if (II->getName() == "ios_app_extension")
25007330f729Sjoerg       NewII = &S.Context.Idents.get("watchos_app_extension");
25017330f729Sjoerg 
25027330f729Sjoerg     if (NewII) {
25037330f729Sjoerg         auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple {
25047330f729Sjoerg           if (Version.empty())
25057330f729Sjoerg             return Version;
25067330f729Sjoerg           auto Major = Version.getMajor();
25077330f729Sjoerg           auto NewMajor = Major >= 9 ? Major - 7 : 0;
25087330f729Sjoerg           if (NewMajor >= 2) {
25097330f729Sjoerg             if (Version.getMinor().hasValue()) {
25107330f729Sjoerg               if (Version.getSubminor().hasValue())
25117330f729Sjoerg                 return VersionTuple(NewMajor, Version.getMinor().getValue(),
25127330f729Sjoerg                                     Version.getSubminor().getValue());
25137330f729Sjoerg               else
25147330f729Sjoerg                 return VersionTuple(NewMajor, Version.getMinor().getValue());
25157330f729Sjoerg             }
25167330f729Sjoerg             return VersionTuple(NewMajor);
25177330f729Sjoerg           }
25187330f729Sjoerg 
25197330f729Sjoerg           return VersionTuple(2, 0);
25207330f729Sjoerg         };
25217330f729Sjoerg 
25227330f729Sjoerg         auto NewIntroduced = adjustWatchOSVersion(Introduced.Version);
25237330f729Sjoerg         auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version);
25247330f729Sjoerg         auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
25257330f729Sjoerg 
25267330f729Sjoerg         AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
25277330f729Sjoerg             ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
25287330f729Sjoerg             NewObsoleted, IsUnavailable, Str, IsStrict, Replacement,
25297330f729Sjoerg             Sema::AMK_None,
25307330f729Sjoerg             PriorityModifier + Sema::AP_InferredFromOtherPlatform);
25317330f729Sjoerg         if (NewAttr)
25327330f729Sjoerg           D->addAttr(NewAttr);
25337330f729Sjoerg       }
25347330f729Sjoerg   } else if (S.Context.getTargetInfo().getTriple().isTvOS()) {
25357330f729Sjoerg     // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning
25367330f729Sjoerg     // matches before the start of the tvOS platform.
25377330f729Sjoerg     IdentifierInfo *NewII = nullptr;
25387330f729Sjoerg     if (II->getName() == "ios")
25397330f729Sjoerg       NewII = &S.Context.Idents.get("tvos");
25407330f729Sjoerg     else if (II->getName() == "ios_app_extension")
25417330f729Sjoerg       NewII = &S.Context.Idents.get("tvos_app_extension");
25427330f729Sjoerg 
25437330f729Sjoerg     if (NewII) {
25447330f729Sjoerg       AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
25457330f729Sjoerg           ND, AL, NewII, true /*Implicit*/, Introduced.Version,
25467330f729Sjoerg           Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict,
25477330f729Sjoerg           Replacement, Sema::AMK_None,
25487330f729Sjoerg           PriorityModifier + Sema::AP_InferredFromOtherPlatform);
25497330f729Sjoerg       if (NewAttr)
25507330f729Sjoerg         D->addAttr(NewAttr);
25517330f729Sjoerg       }
25527330f729Sjoerg   }
25537330f729Sjoerg }
25547330f729Sjoerg 
handleExternalSourceSymbolAttr(Sema & S,Decl * D,const ParsedAttr & AL)25557330f729Sjoerg static void handleExternalSourceSymbolAttr(Sema &S, Decl *D,
25567330f729Sjoerg                                            const ParsedAttr &AL) {
2557*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3))
25587330f729Sjoerg     return;
25597330f729Sjoerg 
25607330f729Sjoerg   StringRef Language;
25617330f729Sjoerg   if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0)))
25627330f729Sjoerg     Language = SE->getString();
25637330f729Sjoerg   StringRef DefinedIn;
25647330f729Sjoerg   if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(1)))
25657330f729Sjoerg     DefinedIn = SE->getString();
25667330f729Sjoerg   bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr;
25677330f729Sjoerg 
25687330f729Sjoerg   D->addAttr(::new (S.Context) ExternalSourceSymbolAttr(
25697330f729Sjoerg       S.Context, AL, Language, DefinedIn, IsGeneratedDeclaration));
25707330f729Sjoerg }
25717330f729Sjoerg 
25727330f729Sjoerg template <class T>
mergeVisibilityAttr(Sema & S,Decl * D,const AttributeCommonInfo & CI,typename T::VisibilityType value)25737330f729Sjoerg static T *mergeVisibilityAttr(Sema &S, Decl *D, const AttributeCommonInfo &CI,
25747330f729Sjoerg                               typename T::VisibilityType value) {
25757330f729Sjoerg   T *existingAttr = D->getAttr<T>();
25767330f729Sjoerg   if (existingAttr) {
25777330f729Sjoerg     typename T::VisibilityType existingValue = existingAttr->getVisibility();
25787330f729Sjoerg     if (existingValue == value)
25797330f729Sjoerg       return nullptr;
25807330f729Sjoerg     S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility);
25817330f729Sjoerg     S.Diag(CI.getLoc(), diag::note_previous_attribute);
25827330f729Sjoerg     D->dropAttr<T>();
25837330f729Sjoerg   }
25847330f729Sjoerg   return ::new (S.Context) T(S.Context, CI, value);
25857330f729Sjoerg }
25867330f729Sjoerg 
mergeVisibilityAttr(Decl * D,const AttributeCommonInfo & CI,VisibilityAttr::VisibilityType Vis)25877330f729Sjoerg VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D,
25887330f729Sjoerg                                           const AttributeCommonInfo &CI,
25897330f729Sjoerg                                           VisibilityAttr::VisibilityType Vis) {
25907330f729Sjoerg   return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, CI, Vis);
25917330f729Sjoerg }
25927330f729Sjoerg 
25937330f729Sjoerg TypeVisibilityAttr *
mergeTypeVisibilityAttr(Decl * D,const AttributeCommonInfo & CI,TypeVisibilityAttr::VisibilityType Vis)25947330f729Sjoerg Sema::mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
25957330f729Sjoerg                               TypeVisibilityAttr::VisibilityType Vis) {
25967330f729Sjoerg   return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, CI, Vis);
25977330f729Sjoerg }
25987330f729Sjoerg 
handleVisibilityAttr(Sema & S,Decl * D,const ParsedAttr & AL,bool isTypeVisibility)25997330f729Sjoerg static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL,
26007330f729Sjoerg                                  bool isTypeVisibility) {
26017330f729Sjoerg   // Visibility attributes don't mean anything on a typedef.
26027330f729Sjoerg   if (isa<TypedefNameDecl>(D)) {
26037330f729Sjoerg     S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL;
26047330f729Sjoerg     return;
26057330f729Sjoerg   }
26067330f729Sjoerg 
26077330f729Sjoerg   // 'type_visibility' can only go on a type or namespace.
26087330f729Sjoerg   if (isTypeVisibility &&
26097330f729Sjoerg       !(isa<TagDecl>(D) ||
26107330f729Sjoerg         isa<ObjCInterfaceDecl>(D) ||
26117330f729Sjoerg         isa<NamespaceDecl>(D))) {
26127330f729Sjoerg     S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
26137330f729Sjoerg         << AL << ExpectedTypeOrNamespace;
26147330f729Sjoerg     return;
26157330f729Sjoerg   }
26167330f729Sjoerg 
26177330f729Sjoerg   // Check that the argument is a string literal.
26187330f729Sjoerg   StringRef TypeStr;
26197330f729Sjoerg   SourceLocation LiteralLoc;
26207330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc))
26217330f729Sjoerg     return;
26227330f729Sjoerg 
26237330f729Sjoerg   VisibilityAttr::VisibilityType type;
26247330f729Sjoerg   if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
26257330f729Sjoerg     S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL
26267330f729Sjoerg                                                                 << TypeStr;
26277330f729Sjoerg     return;
26287330f729Sjoerg   }
26297330f729Sjoerg 
26307330f729Sjoerg   // Complain about attempts to use protected visibility on targets
26317330f729Sjoerg   // (like Darwin) that don't support it.
26327330f729Sjoerg   if (type == VisibilityAttr::Protected &&
26337330f729Sjoerg       !S.Context.getTargetInfo().hasProtectedVisibility()) {
26347330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_protected_visibility);
26357330f729Sjoerg     type = VisibilityAttr::Default;
26367330f729Sjoerg   }
26377330f729Sjoerg 
26387330f729Sjoerg   Attr *newAttr;
26397330f729Sjoerg   if (isTypeVisibility) {
26407330f729Sjoerg     newAttr = S.mergeTypeVisibilityAttr(
26417330f729Sjoerg         D, AL, (TypeVisibilityAttr::VisibilityType)type);
26427330f729Sjoerg   } else {
26437330f729Sjoerg     newAttr = S.mergeVisibilityAttr(D, AL, type);
26447330f729Sjoerg   }
26457330f729Sjoerg   if (newAttr)
26467330f729Sjoerg     D->addAttr(newAttr);
26477330f729Sjoerg }
26487330f729Sjoerg 
handleObjCDirectAttr(Sema & S,Decl * D,const ParsedAttr & AL)2649*e038c9c4Sjoerg static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
2650*e038c9c4Sjoerg   // objc_direct cannot be set on methods declared in the context of a protocol
2651*e038c9c4Sjoerg   if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
2652*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false;
2653*e038c9c4Sjoerg     return;
2654*e038c9c4Sjoerg   }
2655*e038c9c4Sjoerg 
2656*e038c9c4Sjoerg   if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
2657*e038c9c4Sjoerg     handleSimpleAttribute<ObjCDirectAttr>(S, D, AL);
2658*e038c9c4Sjoerg   } else {
2659*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
2660*e038c9c4Sjoerg   }
2661*e038c9c4Sjoerg }
2662*e038c9c4Sjoerg 
handleObjCDirectMembersAttr(Sema & S,Decl * D,const ParsedAttr & AL)2663*e038c9c4Sjoerg static void handleObjCDirectMembersAttr(Sema &S, Decl *D,
2664*e038c9c4Sjoerg                                         const ParsedAttr &AL) {
2665*e038c9c4Sjoerg   if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
2666*e038c9c4Sjoerg     handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
2667*e038c9c4Sjoerg   } else {
2668*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
2669*e038c9c4Sjoerg   }
2670*e038c9c4Sjoerg }
2671*e038c9c4Sjoerg 
handleObjCMethodFamilyAttr(Sema & S,Decl * D,const ParsedAttr & AL)26727330f729Sjoerg static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
26737330f729Sjoerg   const auto *M = cast<ObjCMethodDecl>(D);
26747330f729Sjoerg   if (!AL.isArgIdent(0)) {
26757330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
26767330f729Sjoerg         << AL << 1 << AANT_ArgumentIdentifier;
26777330f729Sjoerg     return;
26787330f729Sjoerg   }
26797330f729Sjoerg 
26807330f729Sjoerg   IdentifierLoc *IL = AL.getArgAsIdent(0);
26817330f729Sjoerg   ObjCMethodFamilyAttr::FamilyKind F;
26827330f729Sjoerg   if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
26837330f729Sjoerg     S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident;
26847330f729Sjoerg     return;
26857330f729Sjoerg   }
26867330f729Sjoerg 
26877330f729Sjoerg   if (F == ObjCMethodFamilyAttr::OMF_init &&
26887330f729Sjoerg       !M->getReturnType()->isObjCObjectPointerType()) {
26897330f729Sjoerg     S.Diag(M->getLocation(), diag::err_init_method_bad_return_type)
26907330f729Sjoerg         << M->getReturnType();
26917330f729Sjoerg     // Ignore the attribute.
26927330f729Sjoerg     return;
26937330f729Sjoerg   }
26947330f729Sjoerg 
26957330f729Sjoerg   D->addAttr(new (S.Context) ObjCMethodFamilyAttr(S.Context, AL, F));
26967330f729Sjoerg }
26977330f729Sjoerg 
handleObjCNSObject(Sema & S,Decl * D,const ParsedAttr & AL)26987330f729Sjoerg static void handleObjCNSObject(Sema &S, Decl *D, const ParsedAttr &AL) {
26997330f729Sjoerg   if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
27007330f729Sjoerg     QualType T = TD->getUnderlyingType();
27017330f729Sjoerg     if (!T->isCARCBridgableType()) {
27027330f729Sjoerg       S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
27037330f729Sjoerg       return;
27047330f729Sjoerg     }
27057330f729Sjoerg   }
27067330f729Sjoerg   else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
27077330f729Sjoerg     QualType T = PD->getType();
27087330f729Sjoerg     if (!T->isCARCBridgableType()) {
27097330f729Sjoerg       S.Diag(PD->getLocation(), diag::err_nsobject_attribute);
27107330f729Sjoerg       return;
27117330f729Sjoerg     }
27127330f729Sjoerg   }
27137330f729Sjoerg   else {
27147330f729Sjoerg     // It is okay to include this attribute on properties, e.g.:
27157330f729Sjoerg     //
27167330f729Sjoerg     //  @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
27177330f729Sjoerg     //
27187330f729Sjoerg     // In this case it follows tradition and suppresses an error in the above
27197330f729Sjoerg     // case.
27207330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
27217330f729Sjoerg   }
27227330f729Sjoerg   D->addAttr(::new (S.Context) ObjCNSObjectAttr(S.Context, AL));
27237330f729Sjoerg }
27247330f729Sjoerg 
handleObjCIndependentClass(Sema & S,Decl * D,const ParsedAttr & AL)27257330f729Sjoerg static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) {
27267330f729Sjoerg   if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
27277330f729Sjoerg     QualType T = TD->getUnderlyingType();
27287330f729Sjoerg     if (!T->isObjCObjectPointerType()) {
27297330f729Sjoerg       S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
27307330f729Sjoerg       return;
27317330f729Sjoerg     }
27327330f729Sjoerg   } else {
27337330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_independentclass_attribute);
27347330f729Sjoerg     return;
27357330f729Sjoerg   }
27367330f729Sjoerg   D->addAttr(::new (S.Context) ObjCIndependentClassAttr(S.Context, AL));
27377330f729Sjoerg }
27387330f729Sjoerg 
handleBlocksAttr(Sema & S,Decl * D,const ParsedAttr & AL)27397330f729Sjoerg static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
27407330f729Sjoerg   if (!AL.isArgIdent(0)) {
27417330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
27427330f729Sjoerg         << AL << 1 << AANT_ArgumentIdentifier;
27437330f729Sjoerg     return;
27447330f729Sjoerg   }
27457330f729Sjoerg 
27467330f729Sjoerg   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
27477330f729Sjoerg   BlocksAttr::BlockType type;
27487330f729Sjoerg   if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
27497330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
27507330f729Sjoerg     return;
27517330f729Sjoerg   }
27527330f729Sjoerg 
27537330f729Sjoerg   D->addAttr(::new (S.Context) BlocksAttr(S.Context, AL, type));
27547330f729Sjoerg }
27557330f729Sjoerg 
handleSentinelAttr(Sema & S,Decl * D,const ParsedAttr & AL)27567330f729Sjoerg static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
27577330f729Sjoerg   unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
27587330f729Sjoerg   if (AL.getNumArgs() > 0) {
27597330f729Sjoerg     Expr *E = AL.getArgAsExpr(0);
2760*e038c9c4Sjoerg     Optional<llvm::APSInt> Idx = llvm::APSInt(32);
27617330f729Sjoerg     if (E->isTypeDependent() || E->isValueDependent() ||
2762*e038c9c4Sjoerg         !(Idx = E->getIntegerConstantExpr(S.Context))) {
27637330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
27647330f729Sjoerg           << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange();
27657330f729Sjoerg       return;
27667330f729Sjoerg     }
27677330f729Sjoerg 
2768*e038c9c4Sjoerg     if (Idx->isSigned() && Idx->isNegative()) {
27697330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero)
27707330f729Sjoerg         << E->getSourceRange();
27717330f729Sjoerg       return;
27727330f729Sjoerg     }
27737330f729Sjoerg 
2774*e038c9c4Sjoerg     sentinel = Idx->getZExtValue();
27757330f729Sjoerg   }
27767330f729Sjoerg 
27777330f729Sjoerg   unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
27787330f729Sjoerg   if (AL.getNumArgs() > 1) {
27797330f729Sjoerg     Expr *E = AL.getArgAsExpr(1);
2780*e038c9c4Sjoerg     Optional<llvm::APSInt> Idx = llvm::APSInt(32);
27817330f729Sjoerg     if (E->isTypeDependent() || E->isValueDependent() ||
2782*e038c9c4Sjoerg         !(Idx = E->getIntegerConstantExpr(S.Context))) {
27837330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
27847330f729Sjoerg           << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange();
27857330f729Sjoerg       return;
27867330f729Sjoerg     }
2787*e038c9c4Sjoerg     nullPos = Idx->getZExtValue();
27887330f729Sjoerg 
2789*e038c9c4Sjoerg     if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) {
27907330f729Sjoerg       // FIXME: This error message could be improved, it would be nice
27917330f729Sjoerg       // to say what the bounds actually are.
27927330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
27937330f729Sjoerg         << E->getSourceRange();
27947330f729Sjoerg       return;
27957330f729Sjoerg     }
27967330f729Sjoerg   }
27977330f729Sjoerg 
27987330f729Sjoerg   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
27997330f729Sjoerg     const FunctionType *FT = FD->getType()->castAs<FunctionType>();
28007330f729Sjoerg     if (isa<FunctionNoProtoType>(FT)) {
28017330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_named_arguments);
28027330f729Sjoerg       return;
28037330f729Sjoerg     }
28047330f729Sjoerg 
28057330f729Sjoerg     if (!cast<FunctionProtoType>(FT)->isVariadic()) {
28067330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
28077330f729Sjoerg       return;
28087330f729Sjoerg     }
28097330f729Sjoerg   } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
28107330f729Sjoerg     if (!MD->isVariadic()) {
28117330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
28127330f729Sjoerg       return;
28137330f729Sjoerg     }
28147330f729Sjoerg   } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
28157330f729Sjoerg     if (!BD->isVariadic()) {
28167330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
28177330f729Sjoerg       return;
28187330f729Sjoerg     }
28197330f729Sjoerg   } else if (const auto *V = dyn_cast<VarDecl>(D)) {
28207330f729Sjoerg     QualType Ty = V->getType();
28217330f729Sjoerg     if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
28227330f729Sjoerg       const FunctionType *FT = Ty->isFunctionPointerType()
28237330f729Sjoerg                                    ? D->getFunctionType()
2824*e038c9c4Sjoerg                                    : Ty->castAs<BlockPointerType>()
2825*e038c9c4Sjoerg                                          ->getPointeeType()
2826*e038c9c4Sjoerg                                          ->castAs<FunctionType>();
28277330f729Sjoerg       if (!cast<FunctionProtoType>(FT)->isVariadic()) {
28287330f729Sjoerg         int m = Ty->isFunctionPointerType() ? 0 : 1;
28297330f729Sjoerg         S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
28307330f729Sjoerg         return;
28317330f729Sjoerg       }
28327330f729Sjoerg     } else {
28337330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
28347330f729Sjoerg           << AL << ExpectedFunctionMethodOrBlock;
28357330f729Sjoerg       return;
28367330f729Sjoerg     }
28377330f729Sjoerg   } else {
28387330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
28397330f729Sjoerg         << AL << ExpectedFunctionMethodOrBlock;
28407330f729Sjoerg     return;
28417330f729Sjoerg   }
28427330f729Sjoerg   D->addAttr(::new (S.Context) SentinelAttr(S.Context, AL, sentinel, nullPos));
28437330f729Sjoerg }
28447330f729Sjoerg 
handleWarnUnusedResult(Sema & S,Decl * D,const ParsedAttr & AL)28457330f729Sjoerg static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) {
28467330f729Sjoerg   if (D->getFunctionType() &&
28477330f729Sjoerg       D->getFunctionType()->getReturnType()->isVoidType() &&
28487330f729Sjoerg       !isa<CXXConstructorDecl>(D)) {
28497330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0;
28507330f729Sjoerg     return;
28517330f729Sjoerg   }
28527330f729Sjoerg   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
28537330f729Sjoerg     if (MD->getReturnType()->isVoidType()) {
28547330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 1;
28557330f729Sjoerg       return;
28567330f729Sjoerg     }
28577330f729Sjoerg 
28587330f729Sjoerg   StringRef Str;
28597330f729Sjoerg   if ((AL.isCXX11Attribute() || AL.isC2xAttribute()) && !AL.getScopeName()) {
2860*e038c9c4Sjoerg     // The standard attribute cannot be applied to variable declarations such
2861*e038c9c4Sjoerg     // as a function pointer.
2862*e038c9c4Sjoerg     if (isa<VarDecl>(D))
2863*e038c9c4Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
2864*e038c9c4Sjoerg           << AL << "functions, classes, or enumerations";
2865*e038c9c4Sjoerg 
28667330f729Sjoerg     // If this is spelled as the standard C++17 attribute, but not in C++17,
28677330f729Sjoerg     // warn about using it as an extension. If there are attribute arguments,
28687330f729Sjoerg     // then claim it's a C++2a extension instead.
28697330f729Sjoerg     // FIXME: If WG14 does not seem likely to adopt the same feature, add an
28707330f729Sjoerg     // extension warning for C2x mode.
28717330f729Sjoerg     const LangOptions &LO = S.getLangOpts();
28727330f729Sjoerg     if (AL.getNumArgs() == 1) {
2873*e038c9c4Sjoerg       if (LO.CPlusPlus && !LO.CPlusPlus20)
2874*e038c9c4Sjoerg         S.Diag(AL.getLoc(), diag::ext_cxx20_attr) << AL;
28757330f729Sjoerg 
28767330f729Sjoerg       // Since this this is spelled [[nodiscard]], get the optional string
28777330f729Sjoerg       // literal. If in C++ mode, but not in C++2a mode, diagnose as an
28787330f729Sjoerg       // extension.
28797330f729Sjoerg       // FIXME: C2x should support this feature as well, even as an extension.
28807330f729Sjoerg       if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, nullptr))
28817330f729Sjoerg         return;
28827330f729Sjoerg     } else if (LO.CPlusPlus && !LO.CPlusPlus17)
28837330f729Sjoerg       S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
28847330f729Sjoerg   }
28857330f729Sjoerg 
28867330f729Sjoerg   D->addAttr(::new (S.Context) WarnUnusedResultAttr(S.Context, AL, Str));
28877330f729Sjoerg }
28887330f729Sjoerg 
handleWeakImportAttr(Sema & S,Decl * D,const ParsedAttr & AL)28897330f729Sjoerg static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
28907330f729Sjoerg   // weak_import only applies to variable & function declarations.
28917330f729Sjoerg   bool isDef = false;
28927330f729Sjoerg   if (!D->canBeWeakImported(isDef)) {
28937330f729Sjoerg     if (isDef)
28947330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition)
28957330f729Sjoerg         << "weak_import";
28967330f729Sjoerg     else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
28977330f729Sjoerg              (S.Context.getTargetInfo().getTriple().isOSDarwin() &&
28987330f729Sjoerg               (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
28997330f729Sjoerg       // Nothing to warn about here.
29007330f729Sjoerg     } else
29017330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
29027330f729Sjoerg           << AL << ExpectedVariableOrFunction;
29037330f729Sjoerg 
29047330f729Sjoerg     return;
29057330f729Sjoerg   }
29067330f729Sjoerg 
29077330f729Sjoerg   D->addAttr(::new (S.Context) WeakImportAttr(S.Context, AL));
29087330f729Sjoerg }
29097330f729Sjoerg 
29107330f729Sjoerg // Handles reqd_work_group_size and work_group_size_hint.
29117330f729Sjoerg template <typename WorkGroupAttr>
handleWorkGroupSize(Sema & S,Decl * D,const ParsedAttr & AL)29127330f729Sjoerg static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
29137330f729Sjoerg   uint32_t WGSize[3];
29147330f729Sjoerg   for (unsigned i = 0; i < 3; ++i) {
29157330f729Sjoerg     const Expr *E = AL.getArgAsExpr(i);
29167330f729Sjoerg     if (!checkUInt32Argument(S, AL, E, WGSize[i], i,
29177330f729Sjoerg                              /*StrictlyUnsigned=*/true))
29187330f729Sjoerg       return;
29197330f729Sjoerg     if (WGSize[i] == 0) {
29207330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
29217330f729Sjoerg           << AL << E->getSourceRange();
29227330f729Sjoerg       return;
29237330f729Sjoerg     }
29247330f729Sjoerg   }
29257330f729Sjoerg 
29267330f729Sjoerg   WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>();
29277330f729Sjoerg   if (Existing && !(Existing->getXDim() == WGSize[0] &&
29287330f729Sjoerg                     Existing->getYDim() == WGSize[1] &&
29297330f729Sjoerg                     Existing->getZDim() == WGSize[2]))
29307330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
29317330f729Sjoerg 
29327330f729Sjoerg   D->addAttr(::new (S.Context)
29337330f729Sjoerg                  WorkGroupAttr(S.Context, AL, WGSize[0], WGSize[1], WGSize[2]));
29347330f729Sjoerg }
29357330f729Sjoerg 
29367330f729Sjoerg // Handles intel_reqd_sub_group_size.
handleSubGroupSize(Sema & S,Decl * D,const ParsedAttr & AL)29377330f729Sjoerg static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
29387330f729Sjoerg   uint32_t SGSize;
29397330f729Sjoerg   const Expr *E = AL.getArgAsExpr(0);
29407330f729Sjoerg   if (!checkUInt32Argument(S, AL, E, SGSize))
29417330f729Sjoerg     return;
29427330f729Sjoerg   if (SGSize == 0) {
29437330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
29447330f729Sjoerg         << AL << E->getSourceRange();
29457330f729Sjoerg     return;
29467330f729Sjoerg   }
29477330f729Sjoerg 
29487330f729Sjoerg   OpenCLIntelReqdSubGroupSizeAttr *Existing =
29497330f729Sjoerg       D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
29507330f729Sjoerg   if (Existing && Existing->getSubGroupSize() != SGSize)
29517330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
29527330f729Sjoerg 
29537330f729Sjoerg   D->addAttr(::new (S.Context)
29547330f729Sjoerg                  OpenCLIntelReqdSubGroupSizeAttr(S.Context, AL, SGSize));
29557330f729Sjoerg }
29567330f729Sjoerg 
handleVecTypeHint(Sema & S,Decl * D,const ParsedAttr & AL)29577330f729Sjoerg static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
29587330f729Sjoerg   if (!AL.hasParsedType()) {
29597330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
29607330f729Sjoerg     return;
29617330f729Sjoerg   }
29627330f729Sjoerg 
29637330f729Sjoerg   TypeSourceInfo *ParmTSI = nullptr;
29647330f729Sjoerg   QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI);
29657330f729Sjoerg   assert(ParmTSI && "no type source info for attribute argument");
29667330f729Sjoerg 
29677330f729Sjoerg   if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
29687330f729Sjoerg       (ParmType->isBooleanType() ||
29697330f729Sjoerg        !ParmType->isIntegralType(S.getASTContext()))) {
2970*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << 2 << AL;
29717330f729Sjoerg     return;
29727330f729Sjoerg   }
29737330f729Sjoerg 
29747330f729Sjoerg   if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
29757330f729Sjoerg     if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
29767330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
29777330f729Sjoerg       return;
29787330f729Sjoerg     }
29797330f729Sjoerg   }
29807330f729Sjoerg 
29817330f729Sjoerg   D->addAttr(::new (S.Context) VecTypeHintAttr(S.Context, AL, ParmTSI));
29827330f729Sjoerg }
29837330f729Sjoerg 
mergeSectionAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Name)29847330f729Sjoerg SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI,
29857330f729Sjoerg                                     StringRef Name) {
29867330f729Sjoerg   // Explicit or partial specializations do not inherit
29877330f729Sjoerg   // the section attribute from the primary template.
29887330f729Sjoerg   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
29897330f729Sjoerg     if (CI.getAttributeSpellingListIndex() == SectionAttr::Declspec_allocate &&
29907330f729Sjoerg         FD->isFunctionTemplateSpecialization())
29917330f729Sjoerg       return nullptr;
29927330f729Sjoerg   }
29937330f729Sjoerg   if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
29947330f729Sjoerg     if (ExistingAttr->getName() == Name)
29957330f729Sjoerg       return nullptr;
29967330f729Sjoerg     Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
29977330f729Sjoerg          << 1 /*section*/;
29987330f729Sjoerg     Diag(CI.getLoc(), diag::note_previous_attribute);
29997330f729Sjoerg     return nullptr;
30007330f729Sjoerg   }
30017330f729Sjoerg   return ::new (Context) SectionAttr(Context, CI, Name);
30027330f729Sjoerg }
30037330f729Sjoerg 
3004*e038c9c4Sjoerg /// Used to implement to perform semantic checking on
3005*e038c9c4Sjoerg /// attribute((section("foo"))) specifiers.
3006*e038c9c4Sjoerg ///
3007*e038c9c4Sjoerg /// In this case, "foo" is passed in to be checked.  If the section
3008*e038c9c4Sjoerg /// specifier is invalid, return an Error that indicates the problem.
3009*e038c9c4Sjoerg ///
3010*e038c9c4Sjoerg /// This is a simple quality of implementation feature to catch errors
3011*e038c9c4Sjoerg /// and give good diagnostics in cases when the assembler or code generator
3012*e038c9c4Sjoerg /// would otherwise reject the section specifier.
isValidSectionSpecifier(StringRef SecName)3013*e038c9c4Sjoerg llvm::Error Sema::isValidSectionSpecifier(StringRef SecName) {
3014*e038c9c4Sjoerg   if (!Context.getTargetInfo().getTriple().isOSDarwin())
3015*e038c9c4Sjoerg     return llvm::Error::success();
3016*e038c9c4Sjoerg 
3017*e038c9c4Sjoerg   // Let MCSectionMachO validate this.
3018*e038c9c4Sjoerg   StringRef Segment, Section;
3019*e038c9c4Sjoerg   unsigned TAA, StubSize;
3020*e038c9c4Sjoerg   bool HasTAA;
3021*e038c9c4Sjoerg   return llvm::MCSectionMachO::ParseSectionSpecifier(SecName, Segment, Section,
3022*e038c9c4Sjoerg                                                      TAA, HasTAA, StubSize);
3023*e038c9c4Sjoerg }
3024*e038c9c4Sjoerg 
checkSectionName(SourceLocation LiteralLoc,StringRef SecName)30257330f729Sjoerg bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
3026*e038c9c4Sjoerg   if (llvm::Error E = isValidSectionSpecifier(SecName)) {
3027*e038c9c4Sjoerg     Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
3028*e038c9c4Sjoerg         << toString(std::move(E)) << 1 /*'section'*/;
30297330f729Sjoerg     return false;
30307330f729Sjoerg   }
30317330f729Sjoerg   return true;
30327330f729Sjoerg }
30337330f729Sjoerg 
handleSectionAttr(Sema & S,Decl * D,const ParsedAttr & AL)30347330f729Sjoerg static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
30357330f729Sjoerg   // Make sure that there is a string literal as the sections's single
30367330f729Sjoerg   // argument.
30377330f729Sjoerg   StringRef Str;
30387330f729Sjoerg   SourceLocation LiteralLoc;
30397330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
30407330f729Sjoerg     return;
30417330f729Sjoerg 
30427330f729Sjoerg   if (!S.checkSectionName(LiteralLoc, Str))
30437330f729Sjoerg     return;
30447330f729Sjoerg 
30457330f729Sjoerg   SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str);
3046*e038c9c4Sjoerg   if (NewAttr) {
30477330f729Sjoerg     D->addAttr(NewAttr);
3048*e038c9c4Sjoerg     if (isa<FunctionDecl, FunctionTemplateDecl, ObjCMethodDecl,
3049*e038c9c4Sjoerg             ObjCPropertyDecl>(D))
3050*e038c9c4Sjoerg       S.UnifySection(NewAttr->getName(),
3051*e038c9c4Sjoerg                      ASTContext::PSF_Execute | ASTContext::PSF_Read,
3052*e038c9c4Sjoerg                      cast<NamedDecl>(D));
3053*e038c9c4Sjoerg   }
30547330f729Sjoerg }
30557330f729Sjoerg 
30567330f729Sjoerg // This is used for `__declspec(code_seg("segname"))` on a decl.
30577330f729Sjoerg // `#pragma code_seg("segname")` uses checkSectionName() instead.
checkCodeSegName(Sema & S,SourceLocation LiteralLoc,StringRef CodeSegName)30587330f729Sjoerg static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc,
30597330f729Sjoerg                              StringRef CodeSegName) {
3060*e038c9c4Sjoerg   if (llvm::Error E = S.isValidSectionSpecifier(CodeSegName)) {
30617330f729Sjoerg     S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
3062*e038c9c4Sjoerg         << toString(std::move(E)) << 0 /*'code-seg'*/;
30637330f729Sjoerg     return false;
30647330f729Sjoerg   }
30657330f729Sjoerg 
30667330f729Sjoerg   return true;
30677330f729Sjoerg }
30687330f729Sjoerg 
mergeCodeSegAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Name)30697330f729Sjoerg CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI,
30707330f729Sjoerg                                     StringRef Name) {
30717330f729Sjoerg   // Explicit or partial specializations do not inherit
30727330f729Sjoerg   // the code_seg attribute from the primary template.
30737330f729Sjoerg   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
30747330f729Sjoerg     if (FD->isFunctionTemplateSpecialization())
30757330f729Sjoerg       return nullptr;
30767330f729Sjoerg   }
30777330f729Sjoerg   if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
30787330f729Sjoerg     if (ExistingAttr->getName() == Name)
30797330f729Sjoerg       return nullptr;
30807330f729Sjoerg     Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
30817330f729Sjoerg          << 0 /*codeseg*/;
30827330f729Sjoerg     Diag(CI.getLoc(), diag::note_previous_attribute);
30837330f729Sjoerg     return nullptr;
30847330f729Sjoerg   }
30857330f729Sjoerg   return ::new (Context) CodeSegAttr(Context, CI, Name);
30867330f729Sjoerg }
30877330f729Sjoerg 
handleCodeSegAttr(Sema & S,Decl * D,const ParsedAttr & AL)30887330f729Sjoerg static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
30897330f729Sjoerg   StringRef Str;
30907330f729Sjoerg   SourceLocation LiteralLoc;
30917330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
30927330f729Sjoerg     return;
30937330f729Sjoerg   if (!checkCodeSegName(S, LiteralLoc, Str))
30947330f729Sjoerg     return;
30957330f729Sjoerg   if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
30967330f729Sjoerg     if (!ExistingAttr->isImplicit()) {
30977330f729Sjoerg       S.Diag(AL.getLoc(),
30987330f729Sjoerg              ExistingAttr->getName() == Str
30997330f729Sjoerg              ? diag::warn_duplicate_codeseg_attribute
31007330f729Sjoerg              : diag::err_conflicting_codeseg_attribute);
31017330f729Sjoerg       return;
31027330f729Sjoerg     }
31037330f729Sjoerg     D->dropAttr<CodeSegAttr>();
31047330f729Sjoerg   }
31057330f729Sjoerg   if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL, Str))
31067330f729Sjoerg     D->addAttr(CSA);
31077330f729Sjoerg }
31087330f729Sjoerg 
31097330f729Sjoerg // Check for things we'd like to warn about. Multiversioning issues are
31107330f729Sjoerg // handled later in the process, once we know how many exist.
checkTargetAttr(SourceLocation LiteralLoc,StringRef AttrStr)31117330f729Sjoerg bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
3112*e038c9c4Sjoerg   enum FirstParam { Unsupported, Duplicate, Unknown };
3113*e038c9c4Sjoerg   enum SecondParam { None, Architecture, Tune };
3114*e038c9c4Sjoerg   if (AttrStr.find("fpmath=") != StringRef::npos)
31157330f729Sjoerg     return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3116*e038c9c4Sjoerg            << Unsupported << None << "fpmath=";
31177330f729Sjoerg 
3118*e038c9c4Sjoerg   // Diagnose use of tune if target doesn't support it.
3119*e038c9c4Sjoerg   if (!Context.getTargetInfo().supportsTargetAttributeTune() &&
3120*e038c9c4Sjoerg       AttrStr.find("tune=") != StringRef::npos)
3121*e038c9c4Sjoerg     return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3122*e038c9c4Sjoerg            << Unsupported << None << "tune=";
3123*e038c9c4Sjoerg 
3124*e038c9c4Sjoerg   ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr);
31257330f729Sjoerg 
31267330f729Sjoerg   if (!ParsedAttrs.Architecture.empty() &&
31277330f729Sjoerg       !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture))
31287330f729Sjoerg     return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3129*e038c9c4Sjoerg            << Unknown << Architecture << ParsedAttrs.Architecture;
3130*e038c9c4Sjoerg 
3131*e038c9c4Sjoerg   if (!ParsedAttrs.Tune.empty() &&
3132*e038c9c4Sjoerg       !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune))
3133*e038c9c4Sjoerg     return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3134*e038c9c4Sjoerg            << Unknown << Tune << ParsedAttrs.Tune;
31357330f729Sjoerg 
31367330f729Sjoerg   if (ParsedAttrs.DuplicateArchitecture)
31377330f729Sjoerg     return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
31387330f729Sjoerg            << Duplicate << None << "arch=";
3139*e038c9c4Sjoerg   if (ParsedAttrs.DuplicateTune)
3140*e038c9c4Sjoerg     return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3141*e038c9c4Sjoerg            << Duplicate << None << "tune=";
31427330f729Sjoerg 
31437330f729Sjoerg   for (const auto &Feature : ParsedAttrs.Features) {
31447330f729Sjoerg     auto CurFeature = StringRef(Feature).drop_front(); // remove + or -.
31457330f729Sjoerg     if (!Context.getTargetInfo().isValidFeatureName(CurFeature))
31467330f729Sjoerg       return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
31477330f729Sjoerg              << Unsupported << None << CurFeature;
31487330f729Sjoerg   }
31497330f729Sjoerg 
3150*e038c9c4Sjoerg   TargetInfo::BranchProtectionInfo BPI;
3151*e038c9c4Sjoerg   StringRef Error;
3152*e038c9c4Sjoerg   if (!ParsedAttrs.BranchProtection.empty() &&
3153*e038c9c4Sjoerg       !Context.getTargetInfo().validateBranchProtection(
3154*e038c9c4Sjoerg           ParsedAttrs.BranchProtection, BPI, Error)) {
3155*e038c9c4Sjoerg     if (Error.empty())
3156*e038c9c4Sjoerg       return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3157*e038c9c4Sjoerg              << Unsupported << None << "branch-protection";
3158*e038c9c4Sjoerg     else
3159*e038c9c4Sjoerg       return Diag(LiteralLoc, diag::err_invalid_branch_protection_spec)
3160*e038c9c4Sjoerg              << Error;
3161*e038c9c4Sjoerg   }
3162*e038c9c4Sjoerg 
31637330f729Sjoerg   return false;
31647330f729Sjoerg }
31657330f729Sjoerg 
handleTargetAttr(Sema & S,Decl * D,const ParsedAttr & AL)31667330f729Sjoerg static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
31677330f729Sjoerg   StringRef Str;
31687330f729Sjoerg   SourceLocation LiteralLoc;
31697330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
31707330f729Sjoerg       S.checkTargetAttr(LiteralLoc, Str))
31717330f729Sjoerg     return;
31727330f729Sjoerg 
31737330f729Sjoerg   TargetAttr *NewAttr = ::new (S.Context) TargetAttr(S.Context, AL, Str);
31747330f729Sjoerg   D->addAttr(NewAttr);
31757330f729Sjoerg }
31767330f729Sjoerg 
handleMinVectorWidthAttr(Sema & S,Decl * D,const ParsedAttr & AL)31777330f729Sjoerg static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
31787330f729Sjoerg   Expr *E = AL.getArgAsExpr(0);
31797330f729Sjoerg   uint32_t VecWidth;
31807330f729Sjoerg   if (!checkUInt32Argument(S, AL, E, VecWidth)) {
31817330f729Sjoerg     AL.setInvalid();
31827330f729Sjoerg     return;
31837330f729Sjoerg   }
31847330f729Sjoerg 
31857330f729Sjoerg   MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>();
31867330f729Sjoerg   if (Existing && Existing->getVectorWidth() != VecWidth) {
31877330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
31887330f729Sjoerg     return;
31897330f729Sjoerg   }
31907330f729Sjoerg 
31917330f729Sjoerg   D->addAttr(::new (S.Context) MinVectorWidthAttr(S.Context, AL, VecWidth));
31927330f729Sjoerg }
31937330f729Sjoerg 
handleCleanupAttr(Sema & S,Decl * D,const ParsedAttr & AL)31947330f729Sjoerg static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
31957330f729Sjoerg   Expr *E = AL.getArgAsExpr(0);
31967330f729Sjoerg   SourceLocation Loc = E->getExprLoc();
31977330f729Sjoerg   FunctionDecl *FD = nullptr;
31987330f729Sjoerg   DeclarationNameInfo NI;
31997330f729Sjoerg 
32007330f729Sjoerg   // gcc only allows for simple identifiers. Since we support more than gcc, we
32017330f729Sjoerg   // will warn the user.
32027330f729Sjoerg   if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
32037330f729Sjoerg     if (DRE->hasQualifier())
32047330f729Sjoerg       S.Diag(Loc, diag::warn_cleanup_ext);
32057330f729Sjoerg     FD = dyn_cast<FunctionDecl>(DRE->getDecl());
32067330f729Sjoerg     NI = DRE->getNameInfo();
32077330f729Sjoerg     if (!FD) {
32087330f729Sjoerg       S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1
32097330f729Sjoerg         << NI.getName();
32107330f729Sjoerg       return;
32117330f729Sjoerg     }
32127330f729Sjoerg   } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
32137330f729Sjoerg     if (ULE->hasExplicitTemplateArgs())
32147330f729Sjoerg       S.Diag(Loc, diag::warn_cleanup_ext);
32157330f729Sjoerg     FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
32167330f729Sjoerg     NI = ULE->getNameInfo();
32177330f729Sjoerg     if (!FD) {
32187330f729Sjoerg       S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
32197330f729Sjoerg         << NI.getName();
32207330f729Sjoerg       if (ULE->getType() == S.Context.OverloadTy)
32217330f729Sjoerg         S.NoteAllOverloadCandidates(ULE);
32227330f729Sjoerg       return;
32237330f729Sjoerg     }
32247330f729Sjoerg   } else {
32257330f729Sjoerg     S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0;
32267330f729Sjoerg     return;
32277330f729Sjoerg   }
32287330f729Sjoerg 
32297330f729Sjoerg   if (FD->getNumParams() != 1) {
32307330f729Sjoerg     S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
32317330f729Sjoerg       << NI.getName();
32327330f729Sjoerg     return;
32337330f729Sjoerg   }
32347330f729Sjoerg 
32357330f729Sjoerg   // We're currently more strict than GCC about what function types we accept.
32367330f729Sjoerg   // If this ever proves to be a problem it should be easy to fix.
32377330f729Sjoerg   QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType());
32387330f729Sjoerg   QualType ParamTy = FD->getParamDecl(0)->getType();
32397330f729Sjoerg   if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
32407330f729Sjoerg                                    ParamTy, Ty) != Sema::Compatible) {
32417330f729Sjoerg     S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type)
32427330f729Sjoerg       << NI.getName() << ParamTy << Ty;
32437330f729Sjoerg     return;
32447330f729Sjoerg   }
32457330f729Sjoerg 
32467330f729Sjoerg   D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD));
32477330f729Sjoerg }
32487330f729Sjoerg 
handleEnumExtensibilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)32497330f729Sjoerg static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
32507330f729Sjoerg                                         const ParsedAttr &AL) {
32517330f729Sjoerg   if (!AL.isArgIdent(0)) {
32527330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
32537330f729Sjoerg         << AL << 0 << AANT_ArgumentIdentifier;
32547330f729Sjoerg     return;
32557330f729Sjoerg   }
32567330f729Sjoerg 
32577330f729Sjoerg   EnumExtensibilityAttr::Kind ExtensibilityKind;
32587330f729Sjoerg   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
32597330f729Sjoerg   if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(),
32607330f729Sjoerg                                                ExtensibilityKind)) {
32617330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
32627330f729Sjoerg     return;
32637330f729Sjoerg   }
32647330f729Sjoerg 
32657330f729Sjoerg   D->addAttr(::new (S.Context)
32667330f729Sjoerg                  EnumExtensibilityAttr(S.Context, AL, ExtensibilityKind));
32677330f729Sjoerg }
32687330f729Sjoerg 
32697330f729Sjoerg /// Handle __attribute__((format_arg((idx)))) attribute based on
32707330f729Sjoerg /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
handleFormatArgAttr(Sema & S,Decl * D,const ParsedAttr & AL)32717330f729Sjoerg static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
32727330f729Sjoerg   Expr *IdxExpr = AL.getArgAsExpr(0);
32737330f729Sjoerg   ParamIdx Idx;
32747330f729Sjoerg   if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx))
32757330f729Sjoerg     return;
32767330f729Sjoerg 
32777330f729Sjoerg   // Make sure the format string is really a string.
32787330f729Sjoerg   QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
32797330f729Sjoerg 
32807330f729Sjoerg   bool NotNSStringTy = !isNSStringType(Ty, S.Context);
32817330f729Sjoerg   if (NotNSStringTy &&
32827330f729Sjoerg       !isCFStringType(Ty, S.Context) &&
32837330f729Sjoerg       (!Ty->isPointerType() ||
32847330f729Sjoerg        !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) {
32857330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_format_attribute_not)
32867330f729Sjoerg         << "a string type" << IdxExpr->getSourceRange()
32877330f729Sjoerg         << getFunctionOrMethodParamRange(D, 0);
32887330f729Sjoerg     return;
32897330f729Sjoerg   }
32907330f729Sjoerg   Ty = getFunctionOrMethodResultType(D);
3291*e038c9c4Sjoerg   if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true) &&
32927330f729Sjoerg       !isCFStringType(Ty, S.Context) &&
32937330f729Sjoerg       (!Ty->isPointerType() ||
32947330f729Sjoerg        !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) {
32957330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_format_attribute_result_not)
32967330f729Sjoerg         << (NotNSStringTy ? "string type" : "NSString")
32977330f729Sjoerg         << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
32987330f729Sjoerg     return;
32997330f729Sjoerg   }
33007330f729Sjoerg 
33017330f729Sjoerg   D->addAttr(::new (S.Context) FormatArgAttr(S.Context, AL, Idx));
33027330f729Sjoerg }
33037330f729Sjoerg 
33047330f729Sjoerg enum FormatAttrKind {
33057330f729Sjoerg   CFStringFormat,
33067330f729Sjoerg   NSStringFormat,
33077330f729Sjoerg   StrftimeFormat,
33087330f729Sjoerg   SupportedFormat,
33097330f729Sjoerg   IgnoredFormat,
33107330f729Sjoerg   InvalidFormat
33117330f729Sjoerg };
33127330f729Sjoerg 
33137330f729Sjoerg /// getFormatAttrKind - Map from format attribute names to supported format
33147330f729Sjoerg /// types.
getFormatAttrKind(StringRef Format)33157330f729Sjoerg static FormatAttrKind getFormatAttrKind(StringRef Format) {
33167330f729Sjoerg   return llvm::StringSwitch<FormatAttrKind>(Format)
33177330f729Sjoerg       // Check for formats that get handled specially.
33187330f729Sjoerg       .Case("NSString", NSStringFormat)
33197330f729Sjoerg       .Case("CFString", CFStringFormat)
33207330f729Sjoerg       .Case("strftime", StrftimeFormat)
33217330f729Sjoerg 
33227330f729Sjoerg       // Otherwise, check for supported formats.
33237330f729Sjoerg       .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
33247330f729Sjoerg       .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
33257330f729Sjoerg       .Case("kprintf", SupportedFormat)         // OpenBSD.
33267330f729Sjoerg       .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
33277330f729Sjoerg       .Case("os_trace", SupportedFormat)
33287330f729Sjoerg       .Case("os_log", SupportedFormat)
33297330f729Sjoerg 
33307330f729Sjoerg       .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
33317330f729Sjoerg       .Default(InvalidFormat);
33327330f729Sjoerg }
33337330f729Sjoerg 
33347330f729Sjoerg /// Handle __attribute__((init_priority(priority))) attributes based on
33357330f729Sjoerg /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
handleInitPriorityAttr(Sema & S,Decl * D,const ParsedAttr & AL)33367330f729Sjoerg static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
33377330f729Sjoerg   if (!S.getLangOpts().CPlusPlus) {
33387330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
33397330f729Sjoerg     return;
33407330f729Sjoerg   }
33417330f729Sjoerg 
33427330f729Sjoerg   if (S.getCurFunctionOrMethodDecl()) {
33437330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
33447330f729Sjoerg     AL.setInvalid();
33457330f729Sjoerg     return;
33467330f729Sjoerg   }
33477330f729Sjoerg   QualType T = cast<VarDecl>(D)->getType();
33487330f729Sjoerg   if (S.Context.getAsArrayType(T))
33497330f729Sjoerg     T = S.Context.getBaseElementType(T);
33507330f729Sjoerg   if (!T->getAs<RecordType>()) {
33517330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
33527330f729Sjoerg     AL.setInvalid();
33537330f729Sjoerg     return;
33547330f729Sjoerg   }
33557330f729Sjoerg 
33567330f729Sjoerg   Expr *E = AL.getArgAsExpr(0);
33577330f729Sjoerg   uint32_t prioritynum;
33587330f729Sjoerg   if (!checkUInt32Argument(S, AL, E, prioritynum)) {
33597330f729Sjoerg     AL.setInvalid();
33607330f729Sjoerg     return;
33617330f729Sjoerg   }
33627330f729Sjoerg 
3363*e038c9c4Sjoerg   // Only perform the priority check if the attribute is outside of a system
3364*e038c9c4Sjoerg   // header. Values <= 100 are reserved for the implementation, and libc++
3365*e038c9c4Sjoerg   // benefits from being able to specify values in that range.
3366*e038c9c4Sjoerg   if ((prioritynum < 101 || prioritynum > 65535) &&
3367*e038c9c4Sjoerg       !S.getSourceManager().isInSystemHeader(AL.getLoc())) {
33687330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
33697330f729Sjoerg         << E->getSourceRange() << AL << 101 << 65535;
33707330f729Sjoerg     AL.setInvalid();
33717330f729Sjoerg     return;
33727330f729Sjoerg   }
33737330f729Sjoerg   D->addAttr(::new (S.Context) InitPriorityAttr(S.Context, AL, prioritynum));
33747330f729Sjoerg }
33757330f729Sjoerg 
mergeFormatAttr(Decl * D,const AttributeCommonInfo & CI,IdentifierInfo * Format,int FormatIdx,int FirstArg)33767330f729Sjoerg FormatAttr *Sema::mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
33777330f729Sjoerg                                   IdentifierInfo *Format, int FormatIdx,
33787330f729Sjoerg                                   int FirstArg) {
33797330f729Sjoerg   // Check whether we already have an equivalent format attribute.
33807330f729Sjoerg   for (auto *F : D->specific_attrs<FormatAttr>()) {
33817330f729Sjoerg     if (F->getType() == Format &&
33827330f729Sjoerg         F->getFormatIdx() == FormatIdx &&
33837330f729Sjoerg         F->getFirstArg() == FirstArg) {
33847330f729Sjoerg       // If we don't have a valid location for this attribute, adopt the
33857330f729Sjoerg       // location.
33867330f729Sjoerg       if (F->getLocation().isInvalid())
33877330f729Sjoerg         F->setRange(CI.getRange());
33887330f729Sjoerg       return nullptr;
33897330f729Sjoerg     }
33907330f729Sjoerg   }
33917330f729Sjoerg 
33927330f729Sjoerg   return ::new (Context) FormatAttr(Context, CI, Format, FormatIdx, FirstArg);
33937330f729Sjoerg }
33947330f729Sjoerg 
33957330f729Sjoerg /// Handle __attribute__((format(type,idx,firstarg))) attributes based on
33967330f729Sjoerg /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
handleFormatAttr(Sema & S,Decl * D,const ParsedAttr & AL)33977330f729Sjoerg static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
33987330f729Sjoerg   if (!AL.isArgIdent(0)) {
33997330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
34007330f729Sjoerg         << AL << 1 << AANT_ArgumentIdentifier;
34017330f729Sjoerg     return;
34027330f729Sjoerg   }
34037330f729Sjoerg 
34047330f729Sjoerg   // In C++ the implicit 'this' function parameter also counts, and they are
34057330f729Sjoerg   // counted from one.
34067330f729Sjoerg   bool HasImplicitThisParam = isInstanceMethod(D);
34077330f729Sjoerg   unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
34087330f729Sjoerg 
34097330f729Sjoerg   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
34107330f729Sjoerg   StringRef Format = II->getName();
34117330f729Sjoerg 
34127330f729Sjoerg   if (normalizeName(Format)) {
34137330f729Sjoerg     // If we've modified the string name, we need a new identifier for it.
34147330f729Sjoerg     II = &S.Context.Idents.get(Format);
34157330f729Sjoerg   }
34167330f729Sjoerg 
34177330f729Sjoerg   // Check for supported formats.
34187330f729Sjoerg   FormatAttrKind Kind = getFormatAttrKind(Format);
34197330f729Sjoerg 
34207330f729Sjoerg   if (Kind == IgnoredFormat)
34217330f729Sjoerg     return;
34227330f729Sjoerg 
34237330f729Sjoerg   if (Kind == InvalidFormat) {
34247330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
34257330f729Sjoerg         << AL << II->getName();
34267330f729Sjoerg     return;
34277330f729Sjoerg   }
34287330f729Sjoerg 
34297330f729Sjoerg   // checks for the 2nd argument
34307330f729Sjoerg   Expr *IdxExpr = AL.getArgAsExpr(1);
34317330f729Sjoerg   uint32_t Idx;
34327330f729Sjoerg   if (!checkUInt32Argument(S, AL, IdxExpr, Idx, 2))
34337330f729Sjoerg     return;
34347330f729Sjoerg 
34357330f729Sjoerg   if (Idx < 1 || Idx > NumArgs) {
34367330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
34377330f729Sjoerg         << AL << 2 << IdxExpr->getSourceRange();
34387330f729Sjoerg     return;
34397330f729Sjoerg   }
34407330f729Sjoerg 
34417330f729Sjoerg   // FIXME: Do we need to bounds check?
34427330f729Sjoerg   unsigned ArgIdx = Idx - 1;
34437330f729Sjoerg 
34447330f729Sjoerg   if (HasImplicitThisParam) {
34457330f729Sjoerg     if (ArgIdx == 0) {
34467330f729Sjoerg       S.Diag(AL.getLoc(),
34477330f729Sjoerg              diag::err_format_attribute_implicit_this_format_string)
34487330f729Sjoerg         << IdxExpr->getSourceRange();
34497330f729Sjoerg       return;
34507330f729Sjoerg     }
34517330f729Sjoerg     ArgIdx--;
34527330f729Sjoerg   }
34537330f729Sjoerg 
34547330f729Sjoerg   // make sure the format string is really a string
34557330f729Sjoerg   QualType Ty = getFunctionOrMethodParamType(D, ArgIdx);
34567330f729Sjoerg 
34577330f729Sjoerg   if (Kind == CFStringFormat) {
34587330f729Sjoerg     if (!isCFStringType(Ty, S.Context)) {
34597330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_format_attribute_not)
34607330f729Sjoerg         << "a CFString" << IdxExpr->getSourceRange()
34617330f729Sjoerg         << getFunctionOrMethodParamRange(D, ArgIdx);
34627330f729Sjoerg       return;
34637330f729Sjoerg     }
34647330f729Sjoerg   } else if (Kind == NSStringFormat) {
34657330f729Sjoerg     // FIXME: do we need to check if the type is NSString*?  What are the
34667330f729Sjoerg     // semantics?
34677330f729Sjoerg     if (!isNSStringType(Ty, S.Context)) {
34687330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_format_attribute_not)
34697330f729Sjoerg         << "an NSString" << IdxExpr->getSourceRange()
34707330f729Sjoerg         << getFunctionOrMethodParamRange(D, ArgIdx);
34717330f729Sjoerg       return;
34727330f729Sjoerg     }
34737330f729Sjoerg   } else if (!Ty->isPointerType() ||
34747330f729Sjoerg              !Ty->castAs<PointerType>()->getPointeeType()->isCharType()) {
34757330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_format_attribute_not)
34767330f729Sjoerg       << "a string type" << IdxExpr->getSourceRange()
34777330f729Sjoerg       << getFunctionOrMethodParamRange(D, ArgIdx);
34787330f729Sjoerg     return;
34797330f729Sjoerg   }
34807330f729Sjoerg 
34817330f729Sjoerg   // check the 3rd argument
34827330f729Sjoerg   Expr *FirstArgExpr = AL.getArgAsExpr(2);
34837330f729Sjoerg   uint32_t FirstArg;
34847330f729Sjoerg   if (!checkUInt32Argument(S, AL, FirstArgExpr, FirstArg, 3))
34857330f729Sjoerg     return;
34867330f729Sjoerg 
34877330f729Sjoerg   // check if the function is variadic if the 3rd argument non-zero
34887330f729Sjoerg   if (FirstArg != 0) {
34897330f729Sjoerg     if (isFunctionOrMethodVariadic(D)) {
34907330f729Sjoerg       ++NumArgs; // +1 for ...
34917330f729Sjoerg     } else {
34927330f729Sjoerg       S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic);
34937330f729Sjoerg       return;
34947330f729Sjoerg     }
34957330f729Sjoerg   }
34967330f729Sjoerg 
34977330f729Sjoerg   // strftime requires FirstArg to be 0 because it doesn't read from any
34987330f729Sjoerg   // variable the input is just the current time + the format string.
34997330f729Sjoerg   if (Kind == StrftimeFormat) {
35007330f729Sjoerg     if (FirstArg != 0) {
35017330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter)
35027330f729Sjoerg         << FirstArgExpr->getSourceRange();
35037330f729Sjoerg       return;
35047330f729Sjoerg     }
35057330f729Sjoerg   // if 0 it disables parameter checking (to use with e.g. va_list)
35067330f729Sjoerg   } else if (FirstArg != 0 && FirstArg != NumArgs) {
35077330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
35087330f729Sjoerg         << AL << 3 << FirstArgExpr->getSourceRange();
35097330f729Sjoerg     return;
35107330f729Sjoerg   }
35117330f729Sjoerg 
35127330f729Sjoerg   FormatAttr *NewAttr = S.mergeFormatAttr(D, AL, II, Idx, FirstArg);
35137330f729Sjoerg   if (NewAttr)
35147330f729Sjoerg     D->addAttr(NewAttr);
35157330f729Sjoerg }
35167330f729Sjoerg 
35177330f729Sjoerg /// Handle __attribute__((callback(CalleeIdx, PayloadIdx0, ...))) attributes.
handleCallbackAttr(Sema & S,Decl * D,const ParsedAttr & AL)35187330f729Sjoerg static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
35197330f729Sjoerg   // The index that identifies the callback callee is mandatory.
35207330f729Sjoerg   if (AL.getNumArgs() == 0) {
35217330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_callback_attribute_no_callee)
35227330f729Sjoerg         << AL.getRange();
35237330f729Sjoerg     return;
35247330f729Sjoerg   }
35257330f729Sjoerg 
35267330f729Sjoerg   bool HasImplicitThisParam = isInstanceMethod(D);
35277330f729Sjoerg   int32_t NumArgs = getFunctionOrMethodNumParams(D);
35287330f729Sjoerg 
35297330f729Sjoerg   FunctionDecl *FD = D->getAsFunction();
35307330f729Sjoerg   assert(FD && "Expected a function declaration!");
35317330f729Sjoerg 
35327330f729Sjoerg   llvm::StringMap<int> NameIdxMapping;
35337330f729Sjoerg   NameIdxMapping["__"] = -1;
35347330f729Sjoerg 
35357330f729Sjoerg   NameIdxMapping["this"] = 0;
35367330f729Sjoerg 
35377330f729Sjoerg   int Idx = 1;
35387330f729Sjoerg   for (const ParmVarDecl *PVD : FD->parameters())
35397330f729Sjoerg     NameIdxMapping[PVD->getName()] = Idx++;
35407330f729Sjoerg 
35417330f729Sjoerg   auto UnknownName = NameIdxMapping.end();
35427330f729Sjoerg 
35437330f729Sjoerg   SmallVector<int, 8> EncodingIndices;
35447330f729Sjoerg   for (unsigned I = 0, E = AL.getNumArgs(); I < E; ++I) {
35457330f729Sjoerg     SourceRange SR;
35467330f729Sjoerg     int32_t ArgIdx;
35477330f729Sjoerg 
35487330f729Sjoerg     if (AL.isArgIdent(I)) {
35497330f729Sjoerg       IdentifierLoc *IdLoc = AL.getArgAsIdent(I);
35507330f729Sjoerg       auto It = NameIdxMapping.find(IdLoc->Ident->getName());
35517330f729Sjoerg       if (It == UnknownName) {
35527330f729Sjoerg         S.Diag(AL.getLoc(), diag::err_callback_attribute_argument_unknown)
35537330f729Sjoerg             << IdLoc->Ident << IdLoc->Loc;
35547330f729Sjoerg         return;
35557330f729Sjoerg       }
35567330f729Sjoerg 
35577330f729Sjoerg       SR = SourceRange(IdLoc->Loc);
35587330f729Sjoerg       ArgIdx = It->second;
35597330f729Sjoerg     } else if (AL.isArgExpr(I)) {
35607330f729Sjoerg       Expr *IdxExpr = AL.getArgAsExpr(I);
35617330f729Sjoerg 
35627330f729Sjoerg       // If the expression is not parseable as an int32_t we have a problem.
35637330f729Sjoerg       if (!checkUInt32Argument(S, AL, IdxExpr, (uint32_t &)ArgIdx, I + 1,
35647330f729Sjoerg                                false)) {
35657330f729Sjoerg         S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
35667330f729Sjoerg             << AL << (I + 1) << IdxExpr->getSourceRange();
35677330f729Sjoerg         return;
35687330f729Sjoerg       }
35697330f729Sjoerg 
35707330f729Sjoerg       // Check oob, excluding the special values, 0 and -1.
35717330f729Sjoerg       if (ArgIdx < -1 || ArgIdx > NumArgs) {
35727330f729Sjoerg         S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
35737330f729Sjoerg             << AL << (I + 1) << IdxExpr->getSourceRange();
35747330f729Sjoerg         return;
35757330f729Sjoerg       }
35767330f729Sjoerg 
35777330f729Sjoerg       SR = IdxExpr->getSourceRange();
35787330f729Sjoerg     } else {
35797330f729Sjoerg       llvm_unreachable("Unexpected ParsedAttr argument type!");
35807330f729Sjoerg     }
35817330f729Sjoerg 
35827330f729Sjoerg     if (ArgIdx == 0 && !HasImplicitThisParam) {
35837330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_callback_implicit_this_not_available)
35847330f729Sjoerg           << (I + 1) << SR;
35857330f729Sjoerg       return;
35867330f729Sjoerg     }
35877330f729Sjoerg 
35887330f729Sjoerg     // Adjust for the case we do not have an implicit "this" parameter. In this
35897330f729Sjoerg     // case we decrease all positive values by 1 to get LLVM argument indices.
35907330f729Sjoerg     if (!HasImplicitThisParam && ArgIdx > 0)
35917330f729Sjoerg       ArgIdx -= 1;
35927330f729Sjoerg 
35937330f729Sjoerg     EncodingIndices.push_back(ArgIdx);
35947330f729Sjoerg   }
35957330f729Sjoerg 
35967330f729Sjoerg   int CalleeIdx = EncodingIndices.front();
35977330f729Sjoerg   // Check if the callee index is proper, thus not "this" and not "unknown".
35987330f729Sjoerg   // This means the "CalleeIdx" has to be non-negative if "HasImplicitThisParam"
35997330f729Sjoerg   // is false and positive if "HasImplicitThisParam" is true.
36007330f729Sjoerg   if (CalleeIdx < (int)HasImplicitThisParam) {
36017330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_callback_attribute_invalid_callee)
36027330f729Sjoerg         << AL.getRange();
36037330f729Sjoerg     return;
36047330f729Sjoerg   }
36057330f729Sjoerg 
36067330f729Sjoerg   // Get the callee type, note the index adjustment as the AST doesn't contain
36077330f729Sjoerg   // the this type (which the callee cannot reference anyway!).
36087330f729Sjoerg   const Type *CalleeType =
36097330f729Sjoerg       getFunctionOrMethodParamType(D, CalleeIdx - HasImplicitThisParam)
36107330f729Sjoerg           .getTypePtr();
36117330f729Sjoerg   if (!CalleeType || !CalleeType->isFunctionPointerType()) {
36127330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type)
36137330f729Sjoerg         << AL.getRange();
36147330f729Sjoerg     return;
36157330f729Sjoerg   }
36167330f729Sjoerg 
36177330f729Sjoerg   const Type *CalleeFnType =
36187330f729Sjoerg       CalleeType->getPointeeType()->getUnqualifiedDesugaredType();
36197330f729Sjoerg 
36207330f729Sjoerg   // TODO: Check the type of the callee arguments.
36217330f729Sjoerg 
36227330f729Sjoerg   const auto *CalleeFnProtoType = dyn_cast<FunctionProtoType>(CalleeFnType);
36237330f729Sjoerg   if (!CalleeFnProtoType) {
36247330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type)
36257330f729Sjoerg         << AL.getRange();
36267330f729Sjoerg     return;
36277330f729Sjoerg   }
36287330f729Sjoerg 
36297330f729Sjoerg   if (CalleeFnProtoType->getNumParams() > EncodingIndices.size() - 1) {
36307330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
36317330f729Sjoerg         << AL << (unsigned)(EncodingIndices.size() - 1);
36327330f729Sjoerg     return;
36337330f729Sjoerg   }
36347330f729Sjoerg 
36357330f729Sjoerg   if (CalleeFnProtoType->getNumParams() < EncodingIndices.size() - 1) {
36367330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
36377330f729Sjoerg         << AL << (unsigned)(EncodingIndices.size() - 1);
36387330f729Sjoerg     return;
36397330f729Sjoerg   }
36407330f729Sjoerg 
36417330f729Sjoerg   if (CalleeFnProtoType->isVariadic()) {
36427330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_callback_callee_is_variadic) << AL.getRange();
36437330f729Sjoerg     return;
36447330f729Sjoerg   }
36457330f729Sjoerg 
36467330f729Sjoerg   // Do not allow multiple callback attributes.
36477330f729Sjoerg   if (D->hasAttr<CallbackAttr>()) {
36487330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_callback_attribute_multiple) << AL.getRange();
36497330f729Sjoerg     return;
36507330f729Sjoerg   }
36517330f729Sjoerg 
36527330f729Sjoerg   D->addAttr(::new (S.Context) CallbackAttr(
36537330f729Sjoerg       S.Context, AL, EncodingIndices.data(), EncodingIndices.size()));
36547330f729Sjoerg }
36557330f729Sjoerg 
isFunctionLike(const Type & T)3656*e038c9c4Sjoerg static bool isFunctionLike(const Type &T) {
3657*e038c9c4Sjoerg   // Check for explicit function types.
3658*e038c9c4Sjoerg   // 'called_once' is only supported in Objective-C and it has
3659*e038c9c4Sjoerg   // function pointers and block pointers.
3660*e038c9c4Sjoerg   return T.isFunctionPointerType() || T.isBlockPointerType();
3661*e038c9c4Sjoerg }
3662*e038c9c4Sjoerg 
3663*e038c9c4Sjoerg /// Handle 'called_once' attribute.
handleCalledOnceAttr(Sema & S,Decl * D,const ParsedAttr & AL)3664*e038c9c4Sjoerg static void handleCalledOnceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3665*e038c9c4Sjoerg   // 'called_once' only applies to parameters representing functions.
3666*e038c9c4Sjoerg   QualType T = cast<ParmVarDecl>(D)->getType();
3667*e038c9c4Sjoerg 
3668*e038c9c4Sjoerg   if (!isFunctionLike(*T)) {
3669*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_called_once_attribute_wrong_type);
3670*e038c9c4Sjoerg     return;
3671*e038c9c4Sjoerg   }
3672*e038c9c4Sjoerg 
3673*e038c9c4Sjoerg   D->addAttr(::new (S.Context) CalledOnceAttr(S.Context, AL));
3674*e038c9c4Sjoerg }
3675*e038c9c4Sjoerg 
handleTransparentUnionAttr(Sema & S,Decl * D,const ParsedAttr & AL)36767330f729Sjoerg static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
36777330f729Sjoerg   // Try to find the underlying union declaration.
36787330f729Sjoerg   RecordDecl *RD = nullptr;
36797330f729Sjoerg   const auto *TD = dyn_cast<TypedefNameDecl>(D);
36807330f729Sjoerg   if (TD && TD->getUnderlyingType()->isUnionType())
36817330f729Sjoerg     RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
36827330f729Sjoerg   else
36837330f729Sjoerg     RD = dyn_cast<RecordDecl>(D);
36847330f729Sjoerg 
36857330f729Sjoerg   if (!RD || !RD->isUnion()) {
36867330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL
36877330f729Sjoerg                                                               << ExpectedUnion;
36887330f729Sjoerg     return;
36897330f729Sjoerg   }
36907330f729Sjoerg 
36917330f729Sjoerg   if (!RD->isCompleteDefinition()) {
36927330f729Sjoerg     if (!RD->isBeingDefined())
36937330f729Sjoerg       S.Diag(AL.getLoc(),
36947330f729Sjoerg              diag::warn_transparent_union_attribute_not_definition);
36957330f729Sjoerg     return;
36967330f729Sjoerg   }
36977330f729Sjoerg 
36987330f729Sjoerg   RecordDecl::field_iterator Field = RD->field_begin(),
36997330f729Sjoerg                           FieldEnd = RD->field_end();
37007330f729Sjoerg   if (Field == FieldEnd) {
37017330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
37027330f729Sjoerg     return;
37037330f729Sjoerg   }
37047330f729Sjoerg 
37057330f729Sjoerg   FieldDecl *FirstField = *Field;
37067330f729Sjoerg   QualType FirstType = FirstField->getType();
37077330f729Sjoerg   if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
37087330f729Sjoerg     S.Diag(FirstField->getLocation(),
37097330f729Sjoerg            diag::warn_transparent_union_attribute_floating)
37107330f729Sjoerg       << FirstType->isVectorType() << FirstType;
37117330f729Sjoerg     return;
37127330f729Sjoerg   }
37137330f729Sjoerg 
37147330f729Sjoerg   if (FirstType->isIncompleteType())
37157330f729Sjoerg     return;
37167330f729Sjoerg   uint64_t FirstSize = S.Context.getTypeSize(FirstType);
37177330f729Sjoerg   uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
37187330f729Sjoerg   for (; Field != FieldEnd; ++Field) {
37197330f729Sjoerg     QualType FieldType = Field->getType();
37207330f729Sjoerg     if (FieldType->isIncompleteType())
37217330f729Sjoerg       return;
37227330f729Sjoerg     // FIXME: this isn't fully correct; we also need to test whether the
37237330f729Sjoerg     // members of the union would all have the same calling convention as the
37247330f729Sjoerg     // first member of the union. Checking just the size and alignment isn't
37257330f729Sjoerg     // sufficient (consider structs passed on the stack instead of in registers
37267330f729Sjoerg     // as an example).
37277330f729Sjoerg     if (S.Context.getTypeSize(FieldType) != FirstSize ||
37287330f729Sjoerg         S.Context.getTypeAlign(FieldType) > FirstAlign) {
37297330f729Sjoerg       // Warn if we drop the attribute.
37307330f729Sjoerg       bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
37317330f729Sjoerg       unsigned FieldBits = isSize ? S.Context.getTypeSize(FieldType)
37327330f729Sjoerg                                   : S.Context.getTypeAlign(FieldType);
37337330f729Sjoerg       S.Diag(Field->getLocation(),
37347330f729Sjoerg              diag::warn_transparent_union_attribute_field_size_align)
3735*e038c9c4Sjoerg           << isSize << *Field << FieldBits;
37367330f729Sjoerg       unsigned FirstBits = isSize ? FirstSize : FirstAlign;
37377330f729Sjoerg       S.Diag(FirstField->getLocation(),
37387330f729Sjoerg              diag::note_transparent_union_first_field_size_align)
37397330f729Sjoerg           << isSize << FirstBits;
37407330f729Sjoerg       return;
37417330f729Sjoerg     }
37427330f729Sjoerg   }
37437330f729Sjoerg 
37447330f729Sjoerg   RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL));
37457330f729Sjoerg }
37467330f729Sjoerg 
AddAnnotationAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Str,MutableArrayRef<Expr * > Args)3747*e038c9c4Sjoerg void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
3748*e038c9c4Sjoerg                              StringRef Str, MutableArrayRef<Expr *> Args) {
3749*e038c9c4Sjoerg   auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI);
3750*e038c9c4Sjoerg   llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
3751*e038c9c4Sjoerg   for (unsigned Idx = 0; Idx < Attr->args_size(); Idx++) {
3752*e038c9c4Sjoerg     Expr *&E = Attr->args_begin()[Idx];
3753*e038c9c4Sjoerg     assert(E && "error are handled before");
3754*e038c9c4Sjoerg     if (E->isValueDependent() || E->isTypeDependent())
3755*e038c9c4Sjoerg       continue;
3756*e038c9c4Sjoerg 
3757*e038c9c4Sjoerg     if (E->getType()->isArrayType())
3758*e038c9c4Sjoerg       E = ImpCastExprToType(E, Context.getPointerType(E->getType()),
3759*e038c9c4Sjoerg                             clang::CK_ArrayToPointerDecay)
3760*e038c9c4Sjoerg               .get();
3761*e038c9c4Sjoerg     if (E->getType()->isFunctionType())
3762*e038c9c4Sjoerg       E = ImplicitCastExpr::Create(Context,
3763*e038c9c4Sjoerg                                    Context.getPointerType(E->getType()),
3764*e038c9c4Sjoerg                                    clang::CK_FunctionToPointerDecay, E, nullptr,
3765*e038c9c4Sjoerg                                    VK_RValue, FPOptionsOverride());
3766*e038c9c4Sjoerg     if (E->isLValue())
3767*e038c9c4Sjoerg       E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),
3768*e038c9c4Sjoerg                                    clang::CK_LValueToRValue, E, nullptr,
3769*e038c9c4Sjoerg                                    VK_RValue, FPOptionsOverride());
3770*e038c9c4Sjoerg 
3771*e038c9c4Sjoerg     Expr::EvalResult Eval;
3772*e038c9c4Sjoerg     Notes.clear();
3773*e038c9c4Sjoerg     Eval.Diag = &Notes;
3774*e038c9c4Sjoerg 
3775*e038c9c4Sjoerg     bool Result =
3776*e038c9c4Sjoerg         E->EvaluateAsConstantExpr(Eval, Context);
3777*e038c9c4Sjoerg 
3778*e038c9c4Sjoerg     /// Result means the expression can be folded to a constant.
3779*e038c9c4Sjoerg     /// Note.empty() means the expression is a valid constant expression in the
3780*e038c9c4Sjoerg     /// current language mode.
3781*e038c9c4Sjoerg     if (!Result || !Notes.empty()) {
3782*e038c9c4Sjoerg       Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)
3783*e038c9c4Sjoerg           << CI << (Idx + 1) << AANT_ArgumentConstantExpr;
3784*e038c9c4Sjoerg       for (auto &Note : Notes)
3785*e038c9c4Sjoerg         Diag(Note.first, Note.second);
3786*e038c9c4Sjoerg       return;
3787*e038c9c4Sjoerg     }
3788*e038c9c4Sjoerg     assert(Eval.Val.hasValue());
3789*e038c9c4Sjoerg     E = ConstantExpr::Create(Context, E, Eval.Val);
3790*e038c9c4Sjoerg   }
3791*e038c9c4Sjoerg   D->addAttr(Attr);
3792*e038c9c4Sjoerg }
3793*e038c9c4Sjoerg 
handleAnnotateAttr(Sema & S,Decl * D,const ParsedAttr & AL)37947330f729Sjoerg static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3795*e038c9c4Sjoerg   // Make sure that there is a string literal as the annotation's first
37967330f729Sjoerg   // argument.
37977330f729Sjoerg   StringRef Str;
37987330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
37997330f729Sjoerg     return;
38007330f729Sjoerg 
3801*e038c9c4Sjoerg   llvm::SmallVector<Expr *, 4> Args;
3802*e038c9c4Sjoerg   Args.reserve(AL.getNumArgs() - 1);
3803*e038c9c4Sjoerg   for (unsigned Idx = 1; Idx < AL.getNumArgs(); Idx++) {
3804*e038c9c4Sjoerg     assert(!AL.isArgIdent(Idx));
3805*e038c9c4Sjoerg     Args.push_back(AL.getArgAsExpr(Idx));
38067330f729Sjoerg   }
38077330f729Sjoerg 
3808*e038c9c4Sjoerg   S.AddAnnotationAttr(D, AL, Str, Args);
38097330f729Sjoerg }
38107330f729Sjoerg 
handleAlignValueAttr(Sema & S,Decl * D,const ParsedAttr & AL)38117330f729Sjoerg static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
38127330f729Sjoerg   S.AddAlignValueAttr(D, AL, AL.getArgAsExpr(0));
38137330f729Sjoerg }
38147330f729Sjoerg 
AddAlignValueAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E)38157330f729Sjoerg void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) {
38167330f729Sjoerg   AlignValueAttr TmpAttr(Context, CI, E);
38177330f729Sjoerg   SourceLocation AttrLoc = CI.getLoc();
38187330f729Sjoerg 
38197330f729Sjoerg   QualType T;
38207330f729Sjoerg   if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
38217330f729Sjoerg     T = TD->getUnderlyingType();
38227330f729Sjoerg   else if (const auto *VD = dyn_cast<ValueDecl>(D))
38237330f729Sjoerg     T = VD->getType();
38247330f729Sjoerg   else
38257330f729Sjoerg     llvm_unreachable("Unknown decl type for align_value");
38267330f729Sjoerg 
38277330f729Sjoerg   if (!T->isDependentType() && !T->isAnyPointerType() &&
38287330f729Sjoerg       !T->isReferenceType() && !T->isMemberPointerType()) {
38297330f729Sjoerg     Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only)
3830*e038c9c4Sjoerg       << &TmpAttr << T << D->getSourceRange();
38317330f729Sjoerg     return;
38327330f729Sjoerg   }
38337330f729Sjoerg 
38347330f729Sjoerg   if (!E->isValueDependent()) {
38357330f729Sjoerg     llvm::APSInt Alignment;
3836*e038c9c4Sjoerg     ExprResult ICE = VerifyIntegerConstantExpression(
3837*e038c9c4Sjoerg         E, &Alignment, diag::err_align_value_attribute_argument_not_int);
38387330f729Sjoerg     if (ICE.isInvalid())
38397330f729Sjoerg       return;
38407330f729Sjoerg 
38417330f729Sjoerg     if (!Alignment.isPowerOf2()) {
38427330f729Sjoerg       Diag(AttrLoc, diag::err_alignment_not_power_of_two)
38437330f729Sjoerg         << E->getSourceRange();
38447330f729Sjoerg       return;
38457330f729Sjoerg     }
38467330f729Sjoerg 
38477330f729Sjoerg     D->addAttr(::new (Context) AlignValueAttr(Context, CI, ICE.get()));
38487330f729Sjoerg     return;
38497330f729Sjoerg   }
38507330f729Sjoerg 
38517330f729Sjoerg   // Save dependent expressions in the AST to be instantiated.
38527330f729Sjoerg   D->addAttr(::new (Context) AlignValueAttr(Context, CI, E));
38537330f729Sjoerg }
38547330f729Sjoerg 
handleAlignedAttr(Sema & S,Decl * D,const ParsedAttr & AL)38557330f729Sjoerg static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
38567330f729Sjoerg   // check the attribute arguments.
38577330f729Sjoerg   if (AL.getNumArgs() > 1) {
38587330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
38597330f729Sjoerg     return;
38607330f729Sjoerg   }
38617330f729Sjoerg 
38627330f729Sjoerg   if (AL.getNumArgs() == 0) {
38637330f729Sjoerg     D->addAttr(::new (S.Context) AlignedAttr(S.Context, AL, true, nullptr));
38647330f729Sjoerg     return;
38657330f729Sjoerg   }
38667330f729Sjoerg 
38677330f729Sjoerg   Expr *E = AL.getArgAsExpr(0);
38687330f729Sjoerg   if (AL.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
38697330f729Sjoerg     S.Diag(AL.getEllipsisLoc(),
38707330f729Sjoerg            diag::err_pack_expansion_without_parameter_packs);
38717330f729Sjoerg     return;
38727330f729Sjoerg   }
38737330f729Sjoerg 
38747330f729Sjoerg   if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
38757330f729Sjoerg     return;
38767330f729Sjoerg 
38777330f729Sjoerg   S.AddAlignedAttr(D, AL, E, AL.isPackExpansion());
38787330f729Sjoerg }
38797330f729Sjoerg 
AddAlignedAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E,bool IsPackExpansion)38807330f729Sjoerg void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
38817330f729Sjoerg                           bool IsPackExpansion) {
38827330f729Sjoerg   AlignedAttr TmpAttr(Context, CI, true, E);
38837330f729Sjoerg   SourceLocation AttrLoc = CI.getLoc();
38847330f729Sjoerg 
38857330f729Sjoerg   // C++11 alignas(...) and C11 _Alignas(...) have additional requirements.
38867330f729Sjoerg   if (TmpAttr.isAlignas()) {
38877330f729Sjoerg     // C++11 [dcl.align]p1:
38887330f729Sjoerg     //   An alignment-specifier may be applied to a variable or to a class
38897330f729Sjoerg     //   data member, but it shall not be applied to a bit-field, a function
38907330f729Sjoerg     //   parameter, the formal parameter of a catch clause, or a variable
38917330f729Sjoerg     //   declared with the register storage class specifier. An
38927330f729Sjoerg     //   alignment-specifier may also be applied to the declaration of a class
38937330f729Sjoerg     //   or enumeration type.
38947330f729Sjoerg     // C11 6.7.5/2:
38957330f729Sjoerg     //   An alignment attribute shall not be specified in a declaration of
38967330f729Sjoerg     //   a typedef, or a bit-field, or a function, or a parameter, or an
38977330f729Sjoerg     //   object declared with the register storage-class specifier.
38987330f729Sjoerg     int DiagKind = -1;
38997330f729Sjoerg     if (isa<ParmVarDecl>(D)) {
39007330f729Sjoerg       DiagKind = 0;
39017330f729Sjoerg     } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
39027330f729Sjoerg       if (VD->getStorageClass() == SC_Register)
39037330f729Sjoerg         DiagKind = 1;
39047330f729Sjoerg       if (VD->isExceptionVariable())
39057330f729Sjoerg         DiagKind = 2;
39067330f729Sjoerg     } else if (const auto *FD = dyn_cast<FieldDecl>(D)) {
39077330f729Sjoerg       if (FD->isBitField())
39087330f729Sjoerg         DiagKind = 3;
39097330f729Sjoerg     } else if (!isa<TagDecl>(D)) {
39107330f729Sjoerg       Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
39117330f729Sjoerg         << (TmpAttr.isC11() ? ExpectedVariableOrField
39127330f729Sjoerg                             : ExpectedVariableFieldOrTag);
39137330f729Sjoerg       return;
39147330f729Sjoerg     }
39157330f729Sjoerg     if (DiagKind != -1) {
39167330f729Sjoerg       Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type)
39177330f729Sjoerg         << &TmpAttr << DiagKind;
39187330f729Sjoerg       return;
39197330f729Sjoerg     }
39207330f729Sjoerg   }
39217330f729Sjoerg 
39227330f729Sjoerg   if (E->isValueDependent()) {
39237330f729Sjoerg     // We can't support a dependent alignment on a non-dependent type,
39247330f729Sjoerg     // because we have no way to model that a type is "alignment-dependent"
39257330f729Sjoerg     // but not dependent in any other way.
39267330f729Sjoerg     if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
39277330f729Sjoerg       if (!TND->getUnderlyingType()->isDependentType()) {
39287330f729Sjoerg         Diag(AttrLoc, diag::err_alignment_dependent_typedef_name)
39297330f729Sjoerg             << E->getSourceRange();
39307330f729Sjoerg         return;
39317330f729Sjoerg       }
39327330f729Sjoerg     }
39337330f729Sjoerg 
39347330f729Sjoerg     // Save dependent expressions in the AST to be instantiated.
39357330f729Sjoerg     AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, E);
39367330f729Sjoerg     AA->setPackExpansion(IsPackExpansion);
39377330f729Sjoerg     D->addAttr(AA);
39387330f729Sjoerg     return;
39397330f729Sjoerg   }
39407330f729Sjoerg 
39417330f729Sjoerg   // FIXME: Cache the number on the AL object?
39427330f729Sjoerg   llvm::APSInt Alignment;
3943*e038c9c4Sjoerg   ExprResult ICE = VerifyIntegerConstantExpression(
3944*e038c9c4Sjoerg       E, &Alignment, diag::err_aligned_attribute_argument_not_int);
39457330f729Sjoerg   if (ICE.isInvalid())
39467330f729Sjoerg     return;
39477330f729Sjoerg 
39487330f729Sjoerg   uint64_t AlignVal = Alignment.getZExtValue();
39497330f729Sjoerg 
39507330f729Sjoerg   // C++11 [dcl.align]p2:
39517330f729Sjoerg   //   -- if the constant expression evaluates to zero, the alignment
39527330f729Sjoerg   //      specifier shall have no effect
39537330f729Sjoerg   // C11 6.7.5p6:
39547330f729Sjoerg   //   An alignment specification of zero has no effect.
39557330f729Sjoerg   if (!(TmpAttr.isAlignas() && !Alignment)) {
39567330f729Sjoerg     if (!llvm::isPowerOf2_64(AlignVal)) {
39577330f729Sjoerg       Diag(AttrLoc, diag::err_alignment_not_power_of_two)
39587330f729Sjoerg         << E->getSourceRange();
39597330f729Sjoerg       return;
39607330f729Sjoerg     }
39617330f729Sjoerg   }
39627330f729Sjoerg 
3963*e038c9c4Sjoerg   unsigned MaximumAlignment = Sema::MaximumAlignment;
3964*e038c9c4Sjoerg   if (Context.getTargetInfo().getTriple().isOSBinFormatCOFF())
3965*e038c9c4Sjoerg     MaximumAlignment = std::min(MaximumAlignment, 8192u);
3966*e038c9c4Sjoerg   if (AlignVal > MaximumAlignment) {
3967*e038c9c4Sjoerg     Diag(AttrLoc, diag::err_attribute_aligned_too_great)
3968*e038c9c4Sjoerg         << MaximumAlignment << E->getSourceRange();
39697330f729Sjoerg     return;
39707330f729Sjoerg   }
39717330f729Sjoerg 
39727330f729Sjoerg   if (Context.getTargetInfo().isTLSSupported()) {
39737330f729Sjoerg     unsigned MaxTLSAlign =
39747330f729Sjoerg         Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
39757330f729Sjoerg             .getQuantity();
39767330f729Sjoerg     const auto *VD = dyn_cast<VarDecl>(D);
39777330f729Sjoerg     if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD &&
39787330f729Sjoerg         VD->getTLSKind() != VarDecl::TLS_None) {
39797330f729Sjoerg       Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
39807330f729Sjoerg           << (unsigned)AlignVal << VD << MaxTLSAlign;
39817330f729Sjoerg       return;
39827330f729Sjoerg     }
39837330f729Sjoerg   }
39847330f729Sjoerg 
39857330f729Sjoerg   AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, ICE.get());
39867330f729Sjoerg   AA->setPackExpansion(IsPackExpansion);
39877330f729Sjoerg   D->addAttr(AA);
39887330f729Sjoerg }
39897330f729Sjoerg 
AddAlignedAttr(Decl * D,const AttributeCommonInfo & CI,TypeSourceInfo * TS,bool IsPackExpansion)39907330f729Sjoerg void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI,
39917330f729Sjoerg                           TypeSourceInfo *TS, bool IsPackExpansion) {
39927330f729Sjoerg   // FIXME: Cache the number on the AL object if non-dependent?
39937330f729Sjoerg   // FIXME: Perform checking of type validity
39947330f729Sjoerg   AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, false, TS);
39957330f729Sjoerg   AA->setPackExpansion(IsPackExpansion);
39967330f729Sjoerg   D->addAttr(AA);
39977330f729Sjoerg }
39987330f729Sjoerg 
CheckAlignasUnderalignment(Decl * D)39997330f729Sjoerg void Sema::CheckAlignasUnderalignment(Decl *D) {
40007330f729Sjoerg   assert(D->hasAttrs() && "no attributes on decl");
40017330f729Sjoerg 
40027330f729Sjoerg   QualType UnderlyingTy, DiagTy;
40037330f729Sjoerg   if (const auto *VD = dyn_cast<ValueDecl>(D)) {
40047330f729Sjoerg     UnderlyingTy = DiagTy = VD->getType();
40057330f729Sjoerg   } else {
40067330f729Sjoerg     UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
40077330f729Sjoerg     if (const auto *ED = dyn_cast<EnumDecl>(D))
40087330f729Sjoerg       UnderlyingTy = ED->getIntegerType();
40097330f729Sjoerg   }
40107330f729Sjoerg   if (DiagTy->isDependentType() || DiagTy->isIncompleteType())
40117330f729Sjoerg     return;
40127330f729Sjoerg 
40137330f729Sjoerg   // C++11 [dcl.align]p5, C11 6.7.5/4:
40147330f729Sjoerg   //   The combined effect of all alignment attributes in a declaration shall
40157330f729Sjoerg   //   not specify an alignment that is less strict than the alignment that
40167330f729Sjoerg   //   would otherwise be required for the entity being declared.
40177330f729Sjoerg   AlignedAttr *AlignasAttr = nullptr;
4018*e038c9c4Sjoerg   AlignedAttr *LastAlignedAttr = nullptr;
40197330f729Sjoerg   unsigned Align = 0;
40207330f729Sjoerg   for (auto *I : D->specific_attrs<AlignedAttr>()) {
40217330f729Sjoerg     if (I->isAlignmentDependent())
40227330f729Sjoerg       return;
40237330f729Sjoerg     if (I->isAlignas())
40247330f729Sjoerg       AlignasAttr = I;
40257330f729Sjoerg     Align = std::max(Align, I->getAlignment(Context));
4026*e038c9c4Sjoerg     LastAlignedAttr = I;
40277330f729Sjoerg   }
40287330f729Sjoerg 
4029*e038c9c4Sjoerg   if (Align && DiagTy->isSizelessType()) {
4030*e038c9c4Sjoerg     Diag(LastAlignedAttr->getLocation(), diag::err_attribute_sizeless_type)
4031*e038c9c4Sjoerg         << LastAlignedAttr << DiagTy;
4032*e038c9c4Sjoerg   } else if (AlignasAttr && Align) {
40337330f729Sjoerg     CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align);
40347330f729Sjoerg     CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy);
40357330f729Sjoerg     if (NaturalAlign > RequestedAlign)
40367330f729Sjoerg       Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned)
40377330f729Sjoerg         << DiagTy << (unsigned)NaturalAlign.getQuantity();
40387330f729Sjoerg   }
40397330f729Sjoerg }
40407330f729Sjoerg 
checkMSInheritanceAttrOnDefinition(CXXRecordDecl * RD,SourceRange Range,bool BestCase,MSInheritanceModel ExplicitModel)40417330f729Sjoerg bool Sema::checkMSInheritanceAttrOnDefinition(
40427330f729Sjoerg     CXXRecordDecl *RD, SourceRange Range, bool BestCase,
4043*e038c9c4Sjoerg     MSInheritanceModel ExplicitModel) {
40447330f729Sjoerg   assert(RD->hasDefinition() && "RD has no definition!");
40457330f729Sjoerg 
40467330f729Sjoerg   // We may not have seen base specifiers or any virtual methods yet.  We will
40477330f729Sjoerg   // have to wait until the record is defined to catch any mismatches.
40487330f729Sjoerg   if (!RD->getDefinition()->isCompleteDefinition())
40497330f729Sjoerg     return false;
40507330f729Sjoerg 
40517330f729Sjoerg   // The unspecified model never matches what a definition could need.
4052*e038c9c4Sjoerg   if (ExplicitModel == MSInheritanceModel::Unspecified)
40537330f729Sjoerg     return false;
40547330f729Sjoerg 
40557330f729Sjoerg   if (BestCase) {
4056*e038c9c4Sjoerg     if (RD->calculateInheritanceModel() == ExplicitModel)
40577330f729Sjoerg       return false;
40587330f729Sjoerg   } else {
4059*e038c9c4Sjoerg     if (RD->calculateInheritanceModel() <= ExplicitModel)
40607330f729Sjoerg       return false;
40617330f729Sjoerg   }
40627330f729Sjoerg 
40637330f729Sjoerg   Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance)
40647330f729Sjoerg       << 0 /*definition*/;
4065*e038c9c4Sjoerg   Diag(RD->getDefinition()->getLocation(), diag::note_defined_here) << RD;
40667330f729Sjoerg   return true;
40677330f729Sjoerg }
40687330f729Sjoerg 
40697330f729Sjoerg /// parseModeAttrArg - Parses attribute mode string and returns parsed type
40707330f729Sjoerg /// attribute.
parseModeAttrArg(Sema & S,StringRef Str,unsigned & DestWidth,bool & IntegerMode,bool & ComplexMode,bool & ExplicitIEEE)40717330f729Sjoerg static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
4072*e038c9c4Sjoerg                              bool &IntegerMode, bool &ComplexMode,
4073*e038c9c4Sjoerg                              bool &ExplicitIEEE) {
40747330f729Sjoerg   IntegerMode = true;
40757330f729Sjoerg   ComplexMode = false;
40767330f729Sjoerg   switch (Str.size()) {
40777330f729Sjoerg   case 2:
40787330f729Sjoerg     switch (Str[0]) {
40797330f729Sjoerg     case 'Q':
40807330f729Sjoerg       DestWidth = 8;
40817330f729Sjoerg       break;
40827330f729Sjoerg     case 'H':
40837330f729Sjoerg       DestWidth = 16;
40847330f729Sjoerg       break;
40857330f729Sjoerg     case 'S':
40867330f729Sjoerg       DestWidth = 32;
40877330f729Sjoerg       break;
40887330f729Sjoerg     case 'D':
40897330f729Sjoerg       DestWidth = 64;
40907330f729Sjoerg       break;
40917330f729Sjoerg     case 'X':
40927330f729Sjoerg       DestWidth = 96;
40937330f729Sjoerg       break;
4094*e038c9c4Sjoerg     case 'K': // KFmode - IEEE quad precision (__float128)
4095*e038c9c4Sjoerg       ExplicitIEEE = true;
4096*e038c9c4Sjoerg       DestWidth = Str[1] == 'I' ? 0 : 128;
4097*e038c9c4Sjoerg       break;
40987330f729Sjoerg     case 'T':
4099*e038c9c4Sjoerg       ExplicitIEEE = false;
41007330f729Sjoerg       DestWidth = 128;
41017330f729Sjoerg       break;
41027330f729Sjoerg     }
41037330f729Sjoerg     if (Str[1] == 'F') {
41047330f729Sjoerg       IntegerMode = false;
41057330f729Sjoerg     } else if (Str[1] == 'C') {
41067330f729Sjoerg       IntegerMode = false;
41077330f729Sjoerg       ComplexMode = true;
41087330f729Sjoerg     } else if (Str[1] != 'I') {
41097330f729Sjoerg       DestWidth = 0;
41107330f729Sjoerg     }
41117330f729Sjoerg     break;
41127330f729Sjoerg   case 4:
41137330f729Sjoerg     // FIXME: glibc uses 'word' to define register_t; this is narrower than a
41147330f729Sjoerg     // pointer on PIC16 and other embedded platforms.
41157330f729Sjoerg     if (Str == "word")
41167330f729Sjoerg       DestWidth = S.Context.getTargetInfo().getRegisterWidth();
41177330f729Sjoerg     else if (Str == "byte")
41187330f729Sjoerg       DestWidth = S.Context.getTargetInfo().getCharWidth();
41197330f729Sjoerg     break;
41207330f729Sjoerg   case 7:
41217330f729Sjoerg     if (Str == "pointer")
41227330f729Sjoerg       DestWidth = S.Context.getTargetInfo().getPointerWidth(0);
41237330f729Sjoerg     break;
41247330f729Sjoerg   case 11:
41257330f729Sjoerg     if (Str == "unwind_word")
41267330f729Sjoerg       DestWidth = S.Context.getTargetInfo().getUnwindWordWidth();
41277330f729Sjoerg     break;
41287330f729Sjoerg   }
41297330f729Sjoerg }
41307330f729Sjoerg 
41317330f729Sjoerg /// handleModeAttr - This attribute modifies the width of a decl with primitive
41327330f729Sjoerg /// type.
41337330f729Sjoerg ///
41347330f729Sjoerg /// Despite what would be logical, the mode attribute is a decl attribute, not a
41357330f729Sjoerg /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
41367330f729Sjoerg /// HImode, not an intermediate pointer.
handleModeAttr(Sema & S,Decl * D,const ParsedAttr & AL)41377330f729Sjoerg static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
41387330f729Sjoerg   // This attribute isn't documented, but glibc uses it.  It changes
41397330f729Sjoerg   // the width of an int or unsigned int to the specified size.
41407330f729Sjoerg   if (!AL.isArgIdent(0)) {
41417330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
41427330f729Sjoerg         << AL << AANT_ArgumentIdentifier;
41437330f729Sjoerg     return;
41447330f729Sjoerg   }
41457330f729Sjoerg 
41467330f729Sjoerg   IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident;
41477330f729Sjoerg 
41487330f729Sjoerg   S.AddModeAttr(D, AL, Name);
41497330f729Sjoerg }
41507330f729Sjoerg 
AddModeAttr(Decl * D,const AttributeCommonInfo & CI,IdentifierInfo * Name,bool InInstantiation)41517330f729Sjoerg void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
41527330f729Sjoerg                        IdentifierInfo *Name, bool InInstantiation) {
41537330f729Sjoerg   StringRef Str = Name->getName();
41547330f729Sjoerg   normalizeName(Str);
41557330f729Sjoerg   SourceLocation AttrLoc = CI.getLoc();
41567330f729Sjoerg 
41577330f729Sjoerg   unsigned DestWidth = 0;
41587330f729Sjoerg   bool IntegerMode = true;
41597330f729Sjoerg   bool ComplexMode = false;
4160*e038c9c4Sjoerg   bool ExplicitIEEE = false;
41617330f729Sjoerg   llvm::APInt VectorSize(64, 0);
41627330f729Sjoerg   if (Str.size() >= 4 && Str[0] == 'V') {
41637330f729Sjoerg     // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
41647330f729Sjoerg     size_t StrSize = Str.size();
41657330f729Sjoerg     size_t VectorStringLength = 0;
41667330f729Sjoerg     while ((VectorStringLength + 1) < StrSize &&
41677330f729Sjoerg            isdigit(Str[VectorStringLength + 1]))
41687330f729Sjoerg       ++VectorStringLength;
41697330f729Sjoerg     if (VectorStringLength &&
41707330f729Sjoerg         !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
41717330f729Sjoerg         VectorSize.isPowerOf2()) {
41727330f729Sjoerg       parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
4173*e038c9c4Sjoerg                        IntegerMode, ComplexMode, ExplicitIEEE);
41747330f729Sjoerg       // Avoid duplicate warning from template instantiation.
41757330f729Sjoerg       if (!InInstantiation)
41767330f729Sjoerg         Diag(AttrLoc, diag::warn_vector_mode_deprecated);
41777330f729Sjoerg     } else {
41787330f729Sjoerg       VectorSize = 0;
41797330f729Sjoerg     }
41807330f729Sjoerg   }
41817330f729Sjoerg 
41827330f729Sjoerg   if (!VectorSize)
4183*e038c9c4Sjoerg     parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode,
4184*e038c9c4Sjoerg                      ExplicitIEEE);
41857330f729Sjoerg 
41867330f729Sjoerg   // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
41877330f729Sjoerg   // and friends, at least with glibc.
41887330f729Sjoerg   // FIXME: Make sure floating-point mappings are accurate
41897330f729Sjoerg   // FIXME: Support XF and TF types
41907330f729Sjoerg   if (!DestWidth) {
41917330f729Sjoerg     Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name;
41927330f729Sjoerg     return;
41937330f729Sjoerg   }
41947330f729Sjoerg 
41957330f729Sjoerg   QualType OldTy;
41967330f729Sjoerg   if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
41977330f729Sjoerg     OldTy = TD->getUnderlyingType();
41987330f729Sjoerg   else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
41997330f729Sjoerg     // Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
42007330f729Sjoerg     // Try to get type from enum declaration, default to int.
42017330f729Sjoerg     OldTy = ED->getIntegerType();
42027330f729Sjoerg     if (OldTy.isNull())
42037330f729Sjoerg       OldTy = Context.IntTy;
42047330f729Sjoerg   } else
42057330f729Sjoerg     OldTy = cast<ValueDecl>(D)->getType();
42067330f729Sjoerg 
42077330f729Sjoerg   if (OldTy->isDependentType()) {
42087330f729Sjoerg     D->addAttr(::new (Context) ModeAttr(Context, CI, Name));
42097330f729Sjoerg     return;
42107330f729Sjoerg   }
42117330f729Sjoerg 
42127330f729Sjoerg   // Base type can also be a vector type (see PR17453).
42137330f729Sjoerg   // Distinguish between base type and base element type.
42147330f729Sjoerg   QualType OldElemTy = OldTy;
42157330f729Sjoerg   if (const auto *VT = OldTy->getAs<VectorType>())
42167330f729Sjoerg     OldElemTy = VT->getElementType();
42177330f729Sjoerg 
42187330f729Sjoerg   // GCC allows 'mode' attribute on enumeration types (even incomplete), except
42197330f729Sjoerg   // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete
42207330f729Sjoerg   // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected.
42217330f729Sjoerg   if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) &&
42227330f729Sjoerg       VectorSize.getBoolValue()) {
42237330f729Sjoerg     Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << CI.getRange();
42247330f729Sjoerg     return;
42257330f729Sjoerg   }
4226*e038c9c4Sjoerg   bool IntegralOrAnyEnumType = (OldElemTy->isIntegralOrEnumerationType() &&
4227*e038c9c4Sjoerg                                 !OldElemTy->isExtIntType()) ||
4228*e038c9c4Sjoerg                                OldElemTy->getAs<EnumType>();
42297330f729Sjoerg 
42307330f729Sjoerg   if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() &&
42317330f729Sjoerg       !IntegralOrAnyEnumType)
42327330f729Sjoerg     Diag(AttrLoc, diag::err_mode_not_primitive);
42337330f729Sjoerg   else if (IntegerMode) {
42347330f729Sjoerg     if (!IntegralOrAnyEnumType)
42357330f729Sjoerg       Diag(AttrLoc, diag::err_mode_wrong_type);
42367330f729Sjoerg   } else if (ComplexMode) {
42377330f729Sjoerg     if (!OldElemTy->isComplexType())
42387330f729Sjoerg       Diag(AttrLoc, diag::err_mode_wrong_type);
42397330f729Sjoerg   } else {
42407330f729Sjoerg     if (!OldElemTy->isFloatingType())
42417330f729Sjoerg       Diag(AttrLoc, diag::err_mode_wrong_type);
42427330f729Sjoerg   }
42437330f729Sjoerg 
42447330f729Sjoerg   QualType NewElemTy;
42457330f729Sjoerg 
42467330f729Sjoerg   if (IntegerMode)
42477330f729Sjoerg     NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
42487330f729Sjoerg                                               OldElemTy->isSignedIntegerType());
42497330f729Sjoerg   else
4250*e038c9c4Sjoerg     NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE);
42517330f729Sjoerg 
42527330f729Sjoerg   if (NewElemTy.isNull()) {
42537330f729Sjoerg     Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
42547330f729Sjoerg     return;
42557330f729Sjoerg   }
42567330f729Sjoerg 
42577330f729Sjoerg   if (ComplexMode) {
42587330f729Sjoerg     NewElemTy = Context.getComplexType(NewElemTy);
42597330f729Sjoerg   }
42607330f729Sjoerg 
42617330f729Sjoerg   QualType NewTy = NewElemTy;
42627330f729Sjoerg   if (VectorSize.getBoolValue()) {
42637330f729Sjoerg     NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(),
42647330f729Sjoerg                                   VectorType::GenericVector);
42657330f729Sjoerg   } else if (const auto *OldVT = OldTy->getAs<VectorType>()) {
42667330f729Sjoerg     // Complex machine mode does not support base vector types.
42677330f729Sjoerg     if (ComplexMode) {
42687330f729Sjoerg       Diag(AttrLoc, diag::err_complex_mode_vector_type);
42697330f729Sjoerg       return;
42707330f729Sjoerg     }
42717330f729Sjoerg     unsigned NumElements = Context.getTypeSize(OldElemTy) *
42727330f729Sjoerg                            OldVT->getNumElements() /
42737330f729Sjoerg                            Context.getTypeSize(NewElemTy);
42747330f729Sjoerg     NewTy =
42757330f729Sjoerg         Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind());
42767330f729Sjoerg   }
42777330f729Sjoerg 
42787330f729Sjoerg   if (NewTy.isNull()) {
42797330f729Sjoerg     Diag(AttrLoc, diag::err_mode_wrong_type);
42807330f729Sjoerg     return;
42817330f729Sjoerg   }
42827330f729Sjoerg 
42837330f729Sjoerg   // Install the new type.
42847330f729Sjoerg   if (auto *TD = dyn_cast<TypedefNameDecl>(D))
42857330f729Sjoerg     TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
42867330f729Sjoerg   else if (auto *ED = dyn_cast<EnumDecl>(D))
42877330f729Sjoerg     ED->setIntegerType(NewTy);
42887330f729Sjoerg   else
42897330f729Sjoerg     cast<ValueDecl>(D)->setType(NewTy);
42907330f729Sjoerg 
42917330f729Sjoerg   D->addAttr(::new (Context) ModeAttr(Context, CI, Name));
42927330f729Sjoerg }
42937330f729Sjoerg 
handleNoDebugAttr(Sema & S,Decl * D,const ParsedAttr & AL)42947330f729Sjoerg static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
42957330f729Sjoerg   D->addAttr(::new (S.Context) NoDebugAttr(S.Context, AL));
42967330f729Sjoerg }
42977330f729Sjoerg 
mergeAlwaysInlineAttr(Decl * D,const AttributeCommonInfo & CI,const IdentifierInfo * Ident)42987330f729Sjoerg AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D,
42997330f729Sjoerg                                               const AttributeCommonInfo &CI,
43007330f729Sjoerg                                               const IdentifierInfo *Ident) {
43017330f729Sjoerg   if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
43027330f729Sjoerg     Diag(CI.getLoc(), diag::warn_attribute_ignored) << Ident;
43037330f729Sjoerg     Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
43047330f729Sjoerg     return nullptr;
43057330f729Sjoerg   }
43067330f729Sjoerg 
43077330f729Sjoerg   if (D->hasAttr<AlwaysInlineAttr>())
43087330f729Sjoerg     return nullptr;
43097330f729Sjoerg 
43107330f729Sjoerg   return ::new (Context) AlwaysInlineAttr(Context, CI);
43117330f729Sjoerg }
43127330f729Sjoerg 
mergeInternalLinkageAttr(Decl * D,const ParsedAttr & AL)43137330f729Sjoerg InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D,
43147330f729Sjoerg                                                     const ParsedAttr &AL) {
43157330f729Sjoerg   if (const auto *VD = dyn_cast<VarDecl>(D)) {
43167330f729Sjoerg     // Attribute applies to Var but not any subclass of it (like ParmVar,
43177330f729Sjoerg     // ImplicitParm or VarTemplateSpecialization).
43187330f729Sjoerg     if (VD->getKind() != Decl::Var) {
43197330f729Sjoerg       Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
43207330f729Sjoerg           << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
43217330f729Sjoerg                                             : ExpectedVariableOrFunction);
43227330f729Sjoerg       return nullptr;
43237330f729Sjoerg     }
43247330f729Sjoerg     // Attribute does not apply to non-static local variables.
43257330f729Sjoerg     if (VD->hasLocalStorage()) {
43267330f729Sjoerg       Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
43277330f729Sjoerg       return nullptr;
43287330f729Sjoerg     }
43297330f729Sjoerg   }
43307330f729Sjoerg 
43317330f729Sjoerg   return ::new (Context) InternalLinkageAttr(Context, AL);
43327330f729Sjoerg }
43337330f729Sjoerg InternalLinkageAttr *
mergeInternalLinkageAttr(Decl * D,const InternalLinkageAttr & AL)43347330f729Sjoerg Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) {
43357330f729Sjoerg   if (const auto *VD = dyn_cast<VarDecl>(D)) {
43367330f729Sjoerg     // Attribute applies to Var but not any subclass of it (like ParmVar,
43377330f729Sjoerg     // ImplicitParm or VarTemplateSpecialization).
43387330f729Sjoerg     if (VD->getKind() != Decl::Var) {
43397330f729Sjoerg       Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type)
43407330f729Sjoerg           << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
43417330f729Sjoerg                                              : ExpectedVariableOrFunction);
43427330f729Sjoerg       return nullptr;
43437330f729Sjoerg     }
43447330f729Sjoerg     // Attribute does not apply to non-static local variables.
43457330f729Sjoerg     if (VD->hasLocalStorage()) {
43467330f729Sjoerg       Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
43477330f729Sjoerg       return nullptr;
43487330f729Sjoerg     }
43497330f729Sjoerg   }
43507330f729Sjoerg 
43517330f729Sjoerg   return ::new (Context) InternalLinkageAttr(Context, AL);
43527330f729Sjoerg }
43537330f729Sjoerg 
mergeMinSizeAttr(Decl * D,const AttributeCommonInfo & CI)43547330f729Sjoerg MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI) {
43557330f729Sjoerg   if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
43567330f729Sjoerg     Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'minsize'";
43577330f729Sjoerg     Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
43587330f729Sjoerg     return nullptr;
43597330f729Sjoerg   }
43607330f729Sjoerg 
43617330f729Sjoerg   if (D->hasAttr<MinSizeAttr>())
43627330f729Sjoerg     return nullptr;
43637330f729Sjoerg 
43647330f729Sjoerg   return ::new (Context) MinSizeAttr(Context, CI);
43657330f729Sjoerg }
43667330f729Sjoerg 
mergeSwiftNameAttr(Decl * D,const SwiftNameAttr & SNA,StringRef Name)4367*e038c9c4Sjoerg SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
4368*e038c9c4Sjoerg                                         StringRef Name) {
4369*e038c9c4Sjoerg   if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) {
4370*e038c9c4Sjoerg     if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) {
4371*e038c9c4Sjoerg       Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible)
4372*e038c9c4Sjoerg           << PrevSNA << &SNA;
4373*e038c9c4Sjoerg       Diag(SNA.getLoc(), diag::note_conflicting_attribute);
4374*e038c9c4Sjoerg     }
43757330f729Sjoerg 
4376*e038c9c4Sjoerg     D->dropAttr<SwiftNameAttr>();
4377*e038c9c4Sjoerg   }
4378*e038c9c4Sjoerg   return ::new (Context) SwiftNameAttr(Context, SNA, Name);
43797330f729Sjoerg }
43807330f729Sjoerg 
mergeOptimizeNoneAttr(Decl * D,const AttributeCommonInfo & CI)43817330f729Sjoerg OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D,
43827330f729Sjoerg                                               const AttributeCommonInfo &CI) {
43837330f729Sjoerg   if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) {
43847330f729Sjoerg     Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline;
43857330f729Sjoerg     Diag(CI.getLoc(), diag::note_conflicting_attribute);
43867330f729Sjoerg     D->dropAttr<AlwaysInlineAttr>();
43877330f729Sjoerg   }
43887330f729Sjoerg   if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) {
43897330f729Sjoerg     Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize;
43907330f729Sjoerg     Diag(CI.getLoc(), diag::note_conflicting_attribute);
43917330f729Sjoerg     D->dropAttr<MinSizeAttr>();
43927330f729Sjoerg   }
43937330f729Sjoerg 
43947330f729Sjoerg   if (D->hasAttr<OptimizeNoneAttr>())
43957330f729Sjoerg     return nullptr;
43967330f729Sjoerg 
43977330f729Sjoerg   return ::new (Context) OptimizeNoneAttr(Context, CI);
43987330f729Sjoerg }
43997330f729Sjoerg 
handleAlwaysInlineAttr(Sema & S,Decl * D,const ParsedAttr & AL)44007330f729Sjoerg static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44017330f729Sjoerg   if (AlwaysInlineAttr *Inline =
44027330f729Sjoerg           S.mergeAlwaysInlineAttr(D, AL, AL.getAttrName()))
44037330f729Sjoerg     D->addAttr(Inline);
44047330f729Sjoerg }
44057330f729Sjoerg 
handleMinSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)44067330f729Sjoerg static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44077330f729Sjoerg   if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(D, AL))
44087330f729Sjoerg     D->addAttr(MinSize);
44097330f729Sjoerg }
44107330f729Sjoerg 
handleOptimizeNoneAttr(Sema & S,Decl * D,const ParsedAttr & AL)44117330f729Sjoerg static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44127330f729Sjoerg   if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(D, AL))
44137330f729Sjoerg     D->addAttr(Optnone);
44147330f729Sjoerg }
44157330f729Sjoerg 
handleConstantAttr(Sema & S,Decl * D,const ParsedAttr & AL)44167330f729Sjoerg static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44177330f729Sjoerg   const auto *VD = cast<VarDecl>(D);
4418*e038c9c4Sjoerg   if (VD->hasLocalStorage()) {
4419*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
44207330f729Sjoerg     return;
44217330f729Sjoerg   }
4422*e038c9c4Sjoerg   // constexpr variable may already get an implicit constant attr, which should
4423*e038c9c4Sjoerg   // be replaced by the explicit constant attr.
4424*e038c9c4Sjoerg   if (auto *A = D->getAttr<CUDAConstantAttr>()) {
4425*e038c9c4Sjoerg     if (!A->isImplicit())
4426*e038c9c4Sjoerg       return;
4427*e038c9c4Sjoerg     D->dropAttr<CUDAConstantAttr>();
4428*e038c9c4Sjoerg   }
44297330f729Sjoerg   D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL));
44307330f729Sjoerg }
44317330f729Sjoerg 
handleSharedAttr(Sema & S,Decl * D,const ParsedAttr & AL)44327330f729Sjoerg static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44337330f729Sjoerg   const auto *VD = cast<VarDecl>(D);
44347330f729Sjoerg   // extern __shared__ is only allowed on arrays with no length (e.g.
44357330f729Sjoerg   // "int x[]").
44367330f729Sjoerg   if (!S.getLangOpts().GPURelocatableDeviceCode && VD->hasExternalStorage() &&
44377330f729Sjoerg       !isa<IncompleteArrayType>(VD->getType())) {
44387330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD;
44397330f729Sjoerg     return;
44407330f729Sjoerg   }
44417330f729Sjoerg   if (S.getLangOpts().CUDA && VD->hasLocalStorage() &&
44427330f729Sjoerg       S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared)
44437330f729Sjoerg           << S.CurrentCUDATarget())
44447330f729Sjoerg     return;
44457330f729Sjoerg   D->addAttr(::new (S.Context) CUDASharedAttr(S.Context, AL));
44467330f729Sjoerg }
44477330f729Sjoerg 
handleGlobalAttr(Sema & S,Decl * D,const ParsedAttr & AL)44487330f729Sjoerg static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44497330f729Sjoerg   const auto *FD = cast<FunctionDecl>(D);
44507330f729Sjoerg   if (!FD->getReturnType()->isVoidType() &&
44517330f729Sjoerg       !FD->getReturnType()->getAs<AutoType>() &&
44527330f729Sjoerg       !FD->getReturnType()->isInstantiationDependentType()) {
44537330f729Sjoerg     SourceRange RTRange = FD->getReturnTypeSourceRange();
44547330f729Sjoerg     S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
44557330f729Sjoerg         << FD->getType()
44567330f729Sjoerg         << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void")
44577330f729Sjoerg                               : FixItHint());
44587330f729Sjoerg     return;
44597330f729Sjoerg   }
44607330f729Sjoerg   if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
44617330f729Sjoerg     if (Method->isInstance()) {
44627330f729Sjoerg       S.Diag(Method->getBeginLoc(), diag::err_kern_is_nonstatic_method)
44637330f729Sjoerg           << Method;
44647330f729Sjoerg       return;
44657330f729Sjoerg     }
44667330f729Sjoerg     S.Diag(Method->getBeginLoc(), diag::warn_kern_is_method) << Method;
44677330f729Sjoerg   }
44687330f729Sjoerg   // Only warn for "inline" when compiling for host, to cut down on noise.
44697330f729Sjoerg   if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice)
44707330f729Sjoerg     S.Diag(FD->getBeginLoc(), diag::warn_kern_is_inline) << FD;
44717330f729Sjoerg 
44727330f729Sjoerg   D->addAttr(::new (S.Context) CUDAGlobalAttr(S.Context, AL));
4473*e038c9c4Sjoerg   // In host compilation the kernel is emitted as a stub function, which is
4474*e038c9c4Sjoerg   // a helper function for launching the kernel. The instructions in the helper
4475*e038c9c4Sjoerg   // function has nothing to do with the source code of the kernel. Do not emit
4476*e038c9c4Sjoerg   // debug info for the stub function to avoid confusing the debugger.
4477*e038c9c4Sjoerg   if (S.LangOpts.HIP && !S.LangOpts.CUDAIsDevice)
4478*e038c9c4Sjoerg     D->addAttr(NoDebugAttr::CreateImplicit(S.Context));
4479*e038c9c4Sjoerg }
4480*e038c9c4Sjoerg 
handleDeviceAttr(Sema & S,Decl * D,const ParsedAttr & AL)4481*e038c9c4Sjoerg static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
4482*e038c9c4Sjoerg   if (const auto *VD = dyn_cast<VarDecl>(D)) {
4483*e038c9c4Sjoerg     if (VD->hasLocalStorage()) {
4484*e038c9c4Sjoerg       S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
4485*e038c9c4Sjoerg       return;
4486*e038c9c4Sjoerg     }
4487*e038c9c4Sjoerg   }
4488*e038c9c4Sjoerg 
4489*e038c9c4Sjoerg   if (auto *A = D->getAttr<CUDADeviceAttr>()) {
4490*e038c9c4Sjoerg     if (!A->isImplicit())
4491*e038c9c4Sjoerg       return;
4492*e038c9c4Sjoerg     D->dropAttr<CUDADeviceAttr>();
4493*e038c9c4Sjoerg   }
4494*e038c9c4Sjoerg   D->addAttr(::new (S.Context) CUDADeviceAttr(S.Context, AL));
4495*e038c9c4Sjoerg }
4496*e038c9c4Sjoerg 
handleManagedAttr(Sema & S,Decl * D,const ParsedAttr & AL)4497*e038c9c4Sjoerg static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
4498*e038c9c4Sjoerg   if (const auto *VD = dyn_cast<VarDecl>(D)) {
4499*e038c9c4Sjoerg     if (VD->hasLocalStorage()) {
4500*e038c9c4Sjoerg       S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
4501*e038c9c4Sjoerg       return;
4502*e038c9c4Sjoerg     }
4503*e038c9c4Sjoerg   }
4504*e038c9c4Sjoerg   if (!D->hasAttr<HIPManagedAttr>())
4505*e038c9c4Sjoerg     D->addAttr(::new (S.Context) HIPManagedAttr(S.Context, AL));
4506*e038c9c4Sjoerg   if (!D->hasAttr<CUDADeviceAttr>())
4507*e038c9c4Sjoerg     D->addAttr(CUDADeviceAttr::CreateImplicit(S.Context));
45087330f729Sjoerg }
45097330f729Sjoerg 
handleGNUInlineAttr(Sema & S,Decl * D,const ParsedAttr & AL)45107330f729Sjoerg static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
45117330f729Sjoerg   const auto *Fn = cast<FunctionDecl>(D);
45127330f729Sjoerg   if (!Fn->isInlineSpecified()) {
45137330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
45147330f729Sjoerg     return;
45157330f729Sjoerg   }
45167330f729Sjoerg 
45177330f729Sjoerg   if (S.LangOpts.CPlusPlus && Fn->getStorageClass() != SC_Extern)
45187330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_gnu_inline_cplusplus_without_extern);
45197330f729Sjoerg 
45207330f729Sjoerg   D->addAttr(::new (S.Context) GNUInlineAttr(S.Context, AL));
45217330f729Sjoerg }
45227330f729Sjoerg 
handleCallConvAttr(Sema & S,Decl * D,const ParsedAttr & AL)45237330f729Sjoerg static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
45247330f729Sjoerg   if (hasDeclarator(D)) return;
45257330f729Sjoerg 
45267330f729Sjoerg   // Diagnostic is emitted elsewhere: here we store the (valid) AL
45277330f729Sjoerg   // in the Decl node for syntactic reasoning, e.g., pretty-printing.
45287330f729Sjoerg   CallingConv CC;
45297330f729Sjoerg   if (S.CheckCallingConvAttr(AL, CC, /*FD*/nullptr))
45307330f729Sjoerg     return;
45317330f729Sjoerg 
45327330f729Sjoerg   if (!isa<ObjCMethodDecl>(D)) {
45337330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
45347330f729Sjoerg         << AL << ExpectedFunctionOrMethod;
45357330f729Sjoerg     return;
45367330f729Sjoerg   }
45377330f729Sjoerg 
45387330f729Sjoerg   switch (AL.getKind()) {
45397330f729Sjoerg   case ParsedAttr::AT_FastCall:
45407330f729Sjoerg     D->addAttr(::new (S.Context) FastCallAttr(S.Context, AL));
45417330f729Sjoerg     return;
45427330f729Sjoerg   case ParsedAttr::AT_StdCall:
45437330f729Sjoerg     D->addAttr(::new (S.Context) StdCallAttr(S.Context, AL));
45447330f729Sjoerg     return;
45457330f729Sjoerg   case ParsedAttr::AT_ThisCall:
45467330f729Sjoerg     D->addAttr(::new (S.Context) ThisCallAttr(S.Context, AL));
45477330f729Sjoerg     return;
45487330f729Sjoerg   case ParsedAttr::AT_CDecl:
45497330f729Sjoerg     D->addAttr(::new (S.Context) CDeclAttr(S.Context, AL));
45507330f729Sjoerg     return;
45517330f729Sjoerg   case ParsedAttr::AT_Pascal:
45527330f729Sjoerg     D->addAttr(::new (S.Context) PascalAttr(S.Context, AL));
45537330f729Sjoerg     return;
45547330f729Sjoerg   case ParsedAttr::AT_SwiftCall:
45557330f729Sjoerg     D->addAttr(::new (S.Context) SwiftCallAttr(S.Context, AL));
45567330f729Sjoerg     return;
45577330f729Sjoerg   case ParsedAttr::AT_VectorCall:
45587330f729Sjoerg     D->addAttr(::new (S.Context) VectorCallAttr(S.Context, AL));
45597330f729Sjoerg     return;
45607330f729Sjoerg   case ParsedAttr::AT_MSABI:
45617330f729Sjoerg     D->addAttr(::new (S.Context) MSABIAttr(S.Context, AL));
45627330f729Sjoerg     return;
45637330f729Sjoerg   case ParsedAttr::AT_SysVABI:
45647330f729Sjoerg     D->addAttr(::new (S.Context) SysVABIAttr(S.Context, AL));
45657330f729Sjoerg     return;
45667330f729Sjoerg   case ParsedAttr::AT_RegCall:
45677330f729Sjoerg     D->addAttr(::new (S.Context) RegCallAttr(S.Context, AL));
45687330f729Sjoerg     return;
45697330f729Sjoerg   case ParsedAttr::AT_Pcs: {
45707330f729Sjoerg     PcsAttr::PCSType PCS;
45717330f729Sjoerg     switch (CC) {
45727330f729Sjoerg     case CC_AAPCS:
45737330f729Sjoerg       PCS = PcsAttr::AAPCS;
45747330f729Sjoerg       break;
45757330f729Sjoerg     case CC_AAPCS_VFP:
45767330f729Sjoerg       PCS = PcsAttr::AAPCS_VFP;
45777330f729Sjoerg       break;
45787330f729Sjoerg     default:
45797330f729Sjoerg       llvm_unreachable("unexpected calling convention in pcs attribute");
45807330f729Sjoerg     }
45817330f729Sjoerg 
45827330f729Sjoerg     D->addAttr(::new (S.Context) PcsAttr(S.Context, AL, PCS));
45837330f729Sjoerg     return;
45847330f729Sjoerg   }
45857330f729Sjoerg   case ParsedAttr::AT_AArch64VectorPcs:
45867330f729Sjoerg     D->addAttr(::new (S.Context) AArch64VectorPcsAttr(S.Context, AL));
45877330f729Sjoerg     return;
45887330f729Sjoerg   case ParsedAttr::AT_IntelOclBicc:
45897330f729Sjoerg     D->addAttr(::new (S.Context) IntelOclBiccAttr(S.Context, AL));
45907330f729Sjoerg     return;
45917330f729Sjoerg   case ParsedAttr::AT_PreserveMost:
45927330f729Sjoerg     D->addAttr(::new (S.Context) PreserveMostAttr(S.Context, AL));
45937330f729Sjoerg     return;
45947330f729Sjoerg   case ParsedAttr::AT_PreserveAll:
45957330f729Sjoerg     D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL));
45967330f729Sjoerg     return;
45977330f729Sjoerg   default:
45987330f729Sjoerg     llvm_unreachable("unexpected attribute kind");
45997330f729Sjoerg   }
46007330f729Sjoerg }
46017330f729Sjoerg 
handleSuppressAttr(Sema & S,Decl * D,const ParsedAttr & AL)46027330f729Sjoerg static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
4603*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1))
46047330f729Sjoerg     return;
46057330f729Sjoerg 
46067330f729Sjoerg   std::vector<StringRef> DiagnosticIdentifiers;
46077330f729Sjoerg   for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
46087330f729Sjoerg     StringRef RuleName;
46097330f729Sjoerg 
46107330f729Sjoerg     if (!S.checkStringLiteralArgumentAttr(AL, I, RuleName, nullptr))
46117330f729Sjoerg       return;
46127330f729Sjoerg 
46137330f729Sjoerg     // FIXME: Warn if the rule name is unknown. This is tricky because only
46147330f729Sjoerg     // clang-tidy knows about available rules.
46157330f729Sjoerg     DiagnosticIdentifiers.push_back(RuleName);
46167330f729Sjoerg   }
46177330f729Sjoerg   D->addAttr(::new (S.Context)
46187330f729Sjoerg                  SuppressAttr(S.Context, AL, DiagnosticIdentifiers.data(),
46197330f729Sjoerg                               DiagnosticIdentifiers.size()));
46207330f729Sjoerg }
46217330f729Sjoerg 
handleLifetimeCategoryAttr(Sema & S,Decl * D,const ParsedAttr & AL)46227330f729Sjoerg static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
46237330f729Sjoerg   TypeSourceInfo *DerefTypeLoc = nullptr;
46247330f729Sjoerg   QualType ParmType;
46257330f729Sjoerg   if (AL.hasParsedType()) {
46267330f729Sjoerg     ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc);
46277330f729Sjoerg 
46287330f729Sjoerg     unsigned SelectIdx = ~0U;
4629*e038c9c4Sjoerg     if (ParmType->isReferenceType())
46307330f729Sjoerg       SelectIdx = 0;
46317330f729Sjoerg     else if (ParmType->isArrayType())
4632*e038c9c4Sjoerg       SelectIdx = 1;
46337330f729Sjoerg 
46347330f729Sjoerg     if (SelectIdx != ~0U) {
46357330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument)
46367330f729Sjoerg           << SelectIdx << AL;
46377330f729Sjoerg       return;
46387330f729Sjoerg     }
46397330f729Sjoerg   }
46407330f729Sjoerg 
46417330f729Sjoerg   // To check if earlier decl attributes do not conflict the newly parsed ones
4642*e038c9c4Sjoerg   // we always add (and check) the attribute to the cannonical decl. We need
4643*e038c9c4Sjoerg   // to repeat the check for attribute mutual exclusion because we're attaching
4644*e038c9c4Sjoerg   // all of the attributes to the canonical declaration rather than the current
4645*e038c9c4Sjoerg   // declaration.
46467330f729Sjoerg   D = D->getCanonicalDecl();
46477330f729Sjoerg   if (AL.getKind() == ParsedAttr::AT_Owner) {
46487330f729Sjoerg     if (checkAttrMutualExclusion<PointerAttr>(S, D, AL))
46497330f729Sjoerg       return;
46507330f729Sjoerg     if (const auto *OAttr = D->getAttr<OwnerAttr>()) {
46517330f729Sjoerg       const Type *ExistingDerefType = OAttr->getDerefTypeLoc()
46527330f729Sjoerg                                           ? OAttr->getDerefType().getTypePtr()
46537330f729Sjoerg                                           : nullptr;
46547330f729Sjoerg       if (ExistingDerefType != ParmType.getTypePtrOrNull()) {
46557330f729Sjoerg         S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
46567330f729Sjoerg             << AL << OAttr;
46577330f729Sjoerg         S.Diag(OAttr->getLocation(), diag::note_conflicting_attribute);
46587330f729Sjoerg       }
46597330f729Sjoerg       return;
46607330f729Sjoerg     }
46617330f729Sjoerg     for (Decl *Redecl : D->redecls()) {
46627330f729Sjoerg       Redecl->addAttr(::new (S.Context) OwnerAttr(S.Context, AL, DerefTypeLoc));
46637330f729Sjoerg     }
46647330f729Sjoerg   } else {
46657330f729Sjoerg     if (checkAttrMutualExclusion<OwnerAttr>(S, D, AL))
46667330f729Sjoerg       return;
46677330f729Sjoerg     if (const auto *PAttr = D->getAttr<PointerAttr>()) {
46687330f729Sjoerg       const Type *ExistingDerefType = PAttr->getDerefTypeLoc()
46697330f729Sjoerg                                           ? PAttr->getDerefType().getTypePtr()
46707330f729Sjoerg                                           : nullptr;
46717330f729Sjoerg       if (ExistingDerefType != ParmType.getTypePtrOrNull()) {
46727330f729Sjoerg         S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
46737330f729Sjoerg             << AL << PAttr;
46747330f729Sjoerg         S.Diag(PAttr->getLocation(), diag::note_conflicting_attribute);
46757330f729Sjoerg       }
46767330f729Sjoerg       return;
46777330f729Sjoerg     }
46787330f729Sjoerg     for (Decl *Redecl : D->redecls()) {
46797330f729Sjoerg       Redecl->addAttr(::new (S.Context)
46807330f729Sjoerg                           PointerAttr(S.Context, AL, DerefTypeLoc));
46817330f729Sjoerg     }
46827330f729Sjoerg   }
46837330f729Sjoerg }
46847330f729Sjoerg 
CheckCallingConvAttr(const ParsedAttr & Attrs,CallingConv & CC,const FunctionDecl * FD)46857330f729Sjoerg bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
46867330f729Sjoerg                                 const FunctionDecl *FD) {
46877330f729Sjoerg   if (Attrs.isInvalid())
46887330f729Sjoerg     return true;
46897330f729Sjoerg 
46907330f729Sjoerg   if (Attrs.hasProcessingCache()) {
46917330f729Sjoerg     CC = (CallingConv) Attrs.getProcessingCache();
46927330f729Sjoerg     return false;
46937330f729Sjoerg   }
46947330f729Sjoerg 
46957330f729Sjoerg   unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0;
4696*e038c9c4Sjoerg   if (!Attrs.checkExactlyNumArgs(*this, ReqArgs)) {
46977330f729Sjoerg     Attrs.setInvalid();
46987330f729Sjoerg     return true;
46997330f729Sjoerg   }
47007330f729Sjoerg 
47017330f729Sjoerg   // TODO: diagnose uses of these conventions on the wrong target.
47027330f729Sjoerg   switch (Attrs.getKind()) {
47037330f729Sjoerg   case ParsedAttr::AT_CDecl:
47047330f729Sjoerg     CC = CC_C;
47057330f729Sjoerg     break;
47067330f729Sjoerg   case ParsedAttr::AT_FastCall:
47077330f729Sjoerg     CC = CC_X86FastCall;
47087330f729Sjoerg     break;
47097330f729Sjoerg   case ParsedAttr::AT_StdCall:
47107330f729Sjoerg     CC = CC_X86StdCall;
47117330f729Sjoerg     break;
47127330f729Sjoerg   case ParsedAttr::AT_ThisCall:
47137330f729Sjoerg     CC = CC_X86ThisCall;
47147330f729Sjoerg     break;
47157330f729Sjoerg   case ParsedAttr::AT_Pascal:
47167330f729Sjoerg     CC = CC_X86Pascal;
47177330f729Sjoerg     break;
47187330f729Sjoerg   case ParsedAttr::AT_SwiftCall:
47197330f729Sjoerg     CC = CC_Swift;
47207330f729Sjoerg     break;
47217330f729Sjoerg   case ParsedAttr::AT_VectorCall:
47227330f729Sjoerg     CC = CC_X86VectorCall;
47237330f729Sjoerg     break;
47247330f729Sjoerg   case ParsedAttr::AT_AArch64VectorPcs:
47257330f729Sjoerg     CC = CC_AArch64VectorCall;
47267330f729Sjoerg     break;
47277330f729Sjoerg   case ParsedAttr::AT_RegCall:
47287330f729Sjoerg     CC = CC_X86RegCall;
47297330f729Sjoerg     break;
47307330f729Sjoerg   case ParsedAttr::AT_MSABI:
47317330f729Sjoerg     CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
47327330f729Sjoerg                                                              CC_Win64;
47337330f729Sjoerg     break;
47347330f729Sjoerg   case ParsedAttr::AT_SysVABI:
47357330f729Sjoerg     CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
47367330f729Sjoerg                                                              CC_C;
47377330f729Sjoerg     break;
47387330f729Sjoerg   case ParsedAttr::AT_Pcs: {
47397330f729Sjoerg     StringRef StrRef;
47407330f729Sjoerg     if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) {
47417330f729Sjoerg       Attrs.setInvalid();
47427330f729Sjoerg       return true;
47437330f729Sjoerg     }
47447330f729Sjoerg     if (StrRef == "aapcs") {
47457330f729Sjoerg       CC = CC_AAPCS;
47467330f729Sjoerg       break;
47477330f729Sjoerg     } else if (StrRef == "aapcs-vfp") {
47487330f729Sjoerg       CC = CC_AAPCS_VFP;
47497330f729Sjoerg       break;
47507330f729Sjoerg     }
47517330f729Sjoerg 
47527330f729Sjoerg     Attrs.setInvalid();
47537330f729Sjoerg     Diag(Attrs.getLoc(), diag::err_invalid_pcs);
47547330f729Sjoerg     return true;
47557330f729Sjoerg   }
47567330f729Sjoerg   case ParsedAttr::AT_IntelOclBicc:
47577330f729Sjoerg     CC = CC_IntelOclBicc;
47587330f729Sjoerg     break;
47597330f729Sjoerg   case ParsedAttr::AT_PreserveMost:
47607330f729Sjoerg     CC = CC_PreserveMost;
47617330f729Sjoerg     break;
47627330f729Sjoerg   case ParsedAttr::AT_PreserveAll:
47637330f729Sjoerg     CC = CC_PreserveAll;
47647330f729Sjoerg     break;
47657330f729Sjoerg   default: llvm_unreachable("unexpected attribute kind");
47667330f729Sjoerg   }
47677330f729Sjoerg 
47687330f729Sjoerg   TargetInfo::CallingConvCheckResult A = TargetInfo::CCCR_OK;
47697330f729Sjoerg   const TargetInfo &TI = Context.getTargetInfo();
47707330f729Sjoerg   // CUDA functions may have host and/or device attributes which indicate
47717330f729Sjoerg   // their targeted execution environment, therefore the calling convention
47727330f729Sjoerg   // of functions in CUDA should be checked against the target deduced based
47737330f729Sjoerg   // on their host/device attributes.
47747330f729Sjoerg   if (LangOpts.CUDA) {
47757330f729Sjoerg     auto *Aux = Context.getAuxTargetInfo();
47767330f729Sjoerg     auto CudaTarget = IdentifyCUDATarget(FD);
47777330f729Sjoerg     bool CheckHost = false, CheckDevice = false;
47787330f729Sjoerg     switch (CudaTarget) {
47797330f729Sjoerg     case CFT_HostDevice:
47807330f729Sjoerg       CheckHost = true;
47817330f729Sjoerg       CheckDevice = true;
47827330f729Sjoerg       break;
47837330f729Sjoerg     case CFT_Host:
47847330f729Sjoerg       CheckHost = true;
47857330f729Sjoerg       break;
47867330f729Sjoerg     case CFT_Device:
47877330f729Sjoerg     case CFT_Global:
47887330f729Sjoerg       CheckDevice = true;
47897330f729Sjoerg       break;
47907330f729Sjoerg     case CFT_InvalidTarget:
47917330f729Sjoerg       llvm_unreachable("unexpected cuda target");
47927330f729Sjoerg     }
47937330f729Sjoerg     auto *HostTI = LangOpts.CUDAIsDevice ? Aux : &TI;
47947330f729Sjoerg     auto *DeviceTI = LangOpts.CUDAIsDevice ? &TI : Aux;
47957330f729Sjoerg     if (CheckHost && HostTI)
47967330f729Sjoerg       A = HostTI->checkCallingConvention(CC);
47977330f729Sjoerg     if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI)
47987330f729Sjoerg       A = DeviceTI->checkCallingConvention(CC);
47997330f729Sjoerg   } else {
48007330f729Sjoerg     A = TI.checkCallingConvention(CC);
48017330f729Sjoerg   }
48027330f729Sjoerg 
48037330f729Sjoerg   switch (A) {
48047330f729Sjoerg   case TargetInfo::CCCR_OK:
48057330f729Sjoerg     break;
48067330f729Sjoerg 
48077330f729Sjoerg   case TargetInfo::CCCR_Ignore:
48087330f729Sjoerg     // Treat an ignored convention as if it was an explicit C calling convention
48097330f729Sjoerg     // attribute. For example, __stdcall on Win x64 functions as __cdecl, so
48107330f729Sjoerg     // that command line flags that change the default convention to
48117330f729Sjoerg     // __vectorcall don't affect declarations marked __stdcall.
48127330f729Sjoerg     CC = CC_C;
48137330f729Sjoerg     break;
48147330f729Sjoerg 
48157330f729Sjoerg   case TargetInfo::CCCR_Error:
48167330f729Sjoerg     Diag(Attrs.getLoc(), diag::error_cconv_unsupported)
48177330f729Sjoerg         << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget;
48187330f729Sjoerg     break;
48197330f729Sjoerg 
48207330f729Sjoerg   case TargetInfo::CCCR_Warning: {
48217330f729Sjoerg     Diag(Attrs.getLoc(), diag::warn_cconv_unsupported)
48227330f729Sjoerg         << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget;
48237330f729Sjoerg 
48247330f729Sjoerg     // This convention is not valid for the target. Use the default function or
48257330f729Sjoerg     // method calling convention.
48267330f729Sjoerg     bool IsCXXMethod = false, IsVariadic = false;
48277330f729Sjoerg     if (FD) {
48287330f729Sjoerg       IsCXXMethod = FD->isCXXInstanceMember();
48297330f729Sjoerg       IsVariadic = FD->isVariadic();
48307330f729Sjoerg     }
48317330f729Sjoerg     CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod);
48327330f729Sjoerg     break;
48337330f729Sjoerg   }
48347330f729Sjoerg   }
48357330f729Sjoerg 
48367330f729Sjoerg   Attrs.setProcessingCache((unsigned) CC);
48377330f729Sjoerg   return false;
48387330f729Sjoerg }
48397330f729Sjoerg 
48407330f729Sjoerg /// Pointer-like types in the default address space.
isValidSwiftContextType(QualType Ty)48417330f729Sjoerg static bool isValidSwiftContextType(QualType Ty) {
48427330f729Sjoerg   if (!Ty->hasPointerRepresentation())
48437330f729Sjoerg     return Ty->isDependentType();
48447330f729Sjoerg   return Ty->getPointeeType().getAddressSpace() == LangAS::Default;
48457330f729Sjoerg }
48467330f729Sjoerg 
48477330f729Sjoerg /// Pointers and references in the default address space.
isValidSwiftIndirectResultType(QualType Ty)48487330f729Sjoerg static bool isValidSwiftIndirectResultType(QualType Ty) {
48497330f729Sjoerg   if (const auto *PtrType = Ty->getAs<PointerType>()) {
48507330f729Sjoerg     Ty = PtrType->getPointeeType();
48517330f729Sjoerg   } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
48527330f729Sjoerg     Ty = RefType->getPointeeType();
48537330f729Sjoerg   } else {
48547330f729Sjoerg     return Ty->isDependentType();
48557330f729Sjoerg   }
48567330f729Sjoerg   return Ty.getAddressSpace() == LangAS::Default;
48577330f729Sjoerg }
48587330f729Sjoerg 
48597330f729Sjoerg /// Pointers and references to pointers in the default address space.
isValidSwiftErrorResultType(QualType Ty)48607330f729Sjoerg static bool isValidSwiftErrorResultType(QualType Ty) {
48617330f729Sjoerg   if (const auto *PtrType = Ty->getAs<PointerType>()) {
48627330f729Sjoerg     Ty = PtrType->getPointeeType();
48637330f729Sjoerg   } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
48647330f729Sjoerg     Ty = RefType->getPointeeType();
48657330f729Sjoerg   } else {
48667330f729Sjoerg     return Ty->isDependentType();
48677330f729Sjoerg   }
48687330f729Sjoerg   if (!Ty.getQualifiers().empty())
48697330f729Sjoerg     return false;
48707330f729Sjoerg   return isValidSwiftContextType(Ty);
48717330f729Sjoerg }
48727330f729Sjoerg 
AddParameterABIAttr(Decl * D,const AttributeCommonInfo & CI,ParameterABI abi)48737330f729Sjoerg void Sema::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
48747330f729Sjoerg                                ParameterABI abi) {
48757330f729Sjoerg 
48767330f729Sjoerg   QualType type = cast<ParmVarDecl>(D)->getType();
48777330f729Sjoerg 
48787330f729Sjoerg   if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
48797330f729Sjoerg     if (existingAttr->getABI() != abi) {
48807330f729Sjoerg       Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
48817330f729Sjoerg           << getParameterABISpelling(abi) << existingAttr;
48827330f729Sjoerg       Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
48837330f729Sjoerg       return;
48847330f729Sjoerg     }
48857330f729Sjoerg   }
48867330f729Sjoerg 
48877330f729Sjoerg   switch (abi) {
48887330f729Sjoerg   case ParameterABI::Ordinary:
48897330f729Sjoerg     llvm_unreachable("explicit attribute for ordinary parameter ABI?");
48907330f729Sjoerg 
48917330f729Sjoerg   case ParameterABI::SwiftContext:
48927330f729Sjoerg     if (!isValidSwiftContextType(type)) {
48937330f729Sjoerg       Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
48947330f729Sjoerg           << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
48957330f729Sjoerg     }
48967330f729Sjoerg     D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
48977330f729Sjoerg     return;
48987330f729Sjoerg 
48997330f729Sjoerg   case ParameterABI::SwiftErrorResult:
49007330f729Sjoerg     if (!isValidSwiftErrorResultType(type)) {
49017330f729Sjoerg       Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
49027330f729Sjoerg           << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type;
49037330f729Sjoerg     }
49047330f729Sjoerg     D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI));
49057330f729Sjoerg     return;
49067330f729Sjoerg 
49077330f729Sjoerg   case ParameterABI::SwiftIndirectResult:
49087330f729Sjoerg     if (!isValidSwiftIndirectResultType(type)) {
49097330f729Sjoerg       Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
49107330f729Sjoerg           << getParameterABISpelling(abi) << /*pointer*/ 0 << type;
49117330f729Sjoerg     }
49127330f729Sjoerg     D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI));
49137330f729Sjoerg     return;
49147330f729Sjoerg   }
49157330f729Sjoerg   llvm_unreachable("bad parameter ABI attribute");
49167330f729Sjoerg }
49177330f729Sjoerg 
49187330f729Sjoerg /// Checks a regparm attribute, returning true if it is ill-formed and
49197330f729Sjoerg /// otherwise setting numParams to the appropriate value.
CheckRegparmAttr(const ParsedAttr & AL,unsigned & numParams)49207330f729Sjoerg bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) {
49217330f729Sjoerg   if (AL.isInvalid())
49227330f729Sjoerg     return true;
49237330f729Sjoerg 
4924*e038c9c4Sjoerg   if (!AL.checkExactlyNumArgs(*this, 1)) {
49257330f729Sjoerg     AL.setInvalid();
49267330f729Sjoerg     return true;
49277330f729Sjoerg   }
49287330f729Sjoerg 
49297330f729Sjoerg   uint32_t NP;
49307330f729Sjoerg   Expr *NumParamsExpr = AL.getArgAsExpr(0);
49317330f729Sjoerg   if (!checkUInt32Argument(*this, AL, NumParamsExpr, NP)) {
49327330f729Sjoerg     AL.setInvalid();
49337330f729Sjoerg     return true;
49347330f729Sjoerg   }
49357330f729Sjoerg 
49367330f729Sjoerg   if (Context.getTargetInfo().getRegParmMax() == 0) {
49377330f729Sjoerg     Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform)
49387330f729Sjoerg       << NumParamsExpr->getSourceRange();
49397330f729Sjoerg     AL.setInvalid();
49407330f729Sjoerg     return true;
49417330f729Sjoerg   }
49427330f729Sjoerg 
49437330f729Sjoerg   numParams = NP;
49447330f729Sjoerg   if (numParams > Context.getTargetInfo().getRegParmMax()) {
49457330f729Sjoerg     Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number)
49467330f729Sjoerg       << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
49477330f729Sjoerg     AL.setInvalid();
49487330f729Sjoerg     return true;
49497330f729Sjoerg   }
49507330f729Sjoerg 
49517330f729Sjoerg   return false;
49527330f729Sjoerg }
49537330f729Sjoerg 
49547330f729Sjoerg // Checks whether an argument of launch_bounds attribute is
49557330f729Sjoerg // acceptable, performs implicit conversion to Rvalue, and returns
49567330f729Sjoerg // non-nullptr Expr result on success. Otherwise, it returns nullptr
49577330f729Sjoerg // and may output an error.
makeLaunchBoundsArgExpr(Sema & S,Expr * E,const CUDALaunchBoundsAttr & AL,const unsigned Idx)49587330f729Sjoerg static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
49597330f729Sjoerg                                      const CUDALaunchBoundsAttr &AL,
49607330f729Sjoerg                                      const unsigned Idx) {
49617330f729Sjoerg   if (S.DiagnoseUnexpandedParameterPack(E))
49627330f729Sjoerg     return nullptr;
49637330f729Sjoerg 
49647330f729Sjoerg   // Accept template arguments for now as they depend on something else.
49657330f729Sjoerg   // We'll get to check them when they eventually get instantiated.
49667330f729Sjoerg   if (E->isValueDependent())
49677330f729Sjoerg     return E;
49687330f729Sjoerg 
4969*e038c9c4Sjoerg   Optional<llvm::APSInt> I = llvm::APSInt(64);
4970*e038c9c4Sjoerg   if (!(I = E->getIntegerConstantExpr(S.Context))) {
49717330f729Sjoerg     S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type)
49727330f729Sjoerg         << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
49737330f729Sjoerg     return nullptr;
49747330f729Sjoerg   }
49757330f729Sjoerg   // Make sure we can fit it in 32 bits.
4976*e038c9c4Sjoerg   if (!I->isIntN(32)) {
4977*e038c9c4Sjoerg     S.Diag(E->getExprLoc(), diag::err_ice_too_large)
4978*e038c9c4Sjoerg         << I->toString(10, false) << 32 << /* Unsigned */ 1;
49797330f729Sjoerg     return nullptr;
49807330f729Sjoerg   }
4981*e038c9c4Sjoerg   if (*I < 0)
49827330f729Sjoerg     S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative)
49837330f729Sjoerg         << &AL << Idx << E->getSourceRange();
49847330f729Sjoerg 
49857330f729Sjoerg   // We may need to perform implicit conversion of the argument.
49867330f729Sjoerg   InitializedEntity Entity = InitializedEntity::InitializeParameter(
49877330f729Sjoerg       S.Context, S.Context.getConstType(S.Context.IntTy), /*consume*/ false);
49887330f729Sjoerg   ExprResult ValArg = S.PerformCopyInitialization(Entity, SourceLocation(), E);
49897330f729Sjoerg   assert(!ValArg.isInvalid() &&
49907330f729Sjoerg          "Unexpected PerformCopyInitialization() failure.");
49917330f729Sjoerg 
49927330f729Sjoerg   return ValArg.getAs<Expr>();
49937330f729Sjoerg }
49947330f729Sjoerg 
AddLaunchBoundsAttr(Decl * D,const AttributeCommonInfo & CI,Expr * MaxThreads,Expr * MinBlocks)49957330f729Sjoerg void Sema::AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
49967330f729Sjoerg                                Expr *MaxThreads, Expr *MinBlocks) {
49977330f729Sjoerg   CUDALaunchBoundsAttr TmpAttr(Context, CI, MaxThreads, MinBlocks);
49987330f729Sjoerg   MaxThreads = makeLaunchBoundsArgExpr(*this, MaxThreads, TmpAttr, 0);
49997330f729Sjoerg   if (MaxThreads == nullptr)
50007330f729Sjoerg     return;
50017330f729Sjoerg 
50027330f729Sjoerg   if (MinBlocks) {
50037330f729Sjoerg     MinBlocks = makeLaunchBoundsArgExpr(*this, MinBlocks, TmpAttr, 1);
50047330f729Sjoerg     if (MinBlocks == nullptr)
50057330f729Sjoerg       return;
50067330f729Sjoerg   }
50077330f729Sjoerg 
50087330f729Sjoerg   D->addAttr(::new (Context)
50097330f729Sjoerg                  CUDALaunchBoundsAttr(Context, CI, MaxThreads, MinBlocks));
50107330f729Sjoerg }
50117330f729Sjoerg 
handleLaunchBoundsAttr(Sema & S,Decl * D,const ParsedAttr & AL)50127330f729Sjoerg static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5013*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
50147330f729Sjoerg     return;
50157330f729Sjoerg 
50167330f729Sjoerg   S.AddLaunchBoundsAttr(D, AL, AL.getArgAsExpr(0),
50177330f729Sjoerg                         AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr);
50187330f729Sjoerg }
50197330f729Sjoerg 
handleArgumentWithTypeTagAttr(Sema & S,Decl * D,const ParsedAttr & AL)50207330f729Sjoerg static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
50217330f729Sjoerg                                           const ParsedAttr &AL) {
50227330f729Sjoerg   if (!AL.isArgIdent(0)) {
50237330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
50247330f729Sjoerg         << AL << /* arg num = */ 1 << AANT_ArgumentIdentifier;
50257330f729Sjoerg     return;
50267330f729Sjoerg   }
50277330f729Sjoerg 
50287330f729Sjoerg   ParamIdx ArgumentIdx;
50297330f729Sjoerg   if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1),
50307330f729Sjoerg                                            ArgumentIdx))
50317330f729Sjoerg     return;
50327330f729Sjoerg 
50337330f729Sjoerg   ParamIdx TypeTagIdx;
50347330f729Sjoerg   if (!checkFunctionOrMethodParameterIndex(S, D, AL, 3, AL.getArgAsExpr(2),
50357330f729Sjoerg                                            TypeTagIdx))
50367330f729Sjoerg     return;
50377330f729Sjoerg 
50387330f729Sjoerg   bool IsPointer = AL.getAttrName()->getName() == "pointer_with_type_tag";
50397330f729Sjoerg   if (IsPointer) {
50407330f729Sjoerg     // Ensure that buffer has a pointer type.
50417330f729Sjoerg     unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex();
50427330f729Sjoerg     if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) ||
50437330f729Sjoerg         !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType())
50447330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL << 0;
50457330f729Sjoerg   }
50467330f729Sjoerg 
50477330f729Sjoerg   D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(
50487330f729Sjoerg       S.Context, AL, AL.getArgAsIdent(0)->Ident, ArgumentIdx, TypeTagIdx,
50497330f729Sjoerg       IsPointer));
50507330f729Sjoerg }
50517330f729Sjoerg 
handleTypeTagForDatatypeAttr(Sema & S,Decl * D,const ParsedAttr & AL)50527330f729Sjoerg static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
50537330f729Sjoerg                                          const ParsedAttr &AL) {
50547330f729Sjoerg   if (!AL.isArgIdent(0)) {
50557330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
50567330f729Sjoerg         << AL << 1 << AANT_ArgumentIdentifier;
50577330f729Sjoerg     return;
50587330f729Sjoerg   }
50597330f729Sjoerg 
5060*e038c9c4Sjoerg   if (!AL.checkExactlyNumArgs(S, 1))
50617330f729Sjoerg     return;
50627330f729Sjoerg 
50637330f729Sjoerg   if (!isa<VarDecl>(D)) {
50647330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
50657330f729Sjoerg         << AL << ExpectedVariable;
50667330f729Sjoerg     return;
50677330f729Sjoerg   }
50687330f729Sjoerg 
50697330f729Sjoerg   IdentifierInfo *PointerKind = AL.getArgAsIdent(0)->Ident;
50707330f729Sjoerg   TypeSourceInfo *MatchingCTypeLoc = nullptr;
50717330f729Sjoerg   S.GetTypeFromParser(AL.getMatchingCType(), &MatchingCTypeLoc);
50727330f729Sjoerg   assert(MatchingCTypeLoc && "no type source info for attribute argument");
50737330f729Sjoerg 
50747330f729Sjoerg   D->addAttr(::new (S.Context) TypeTagForDatatypeAttr(
50757330f729Sjoerg       S.Context, AL, PointerKind, MatchingCTypeLoc, AL.getLayoutCompatible(),
50767330f729Sjoerg       AL.getMustBeNull()));
50777330f729Sjoerg }
50787330f729Sjoerg 
handleXRayLogArgsAttr(Sema & S,Decl * D,const ParsedAttr & AL)50797330f729Sjoerg static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
50807330f729Sjoerg   ParamIdx ArgCount;
50817330f729Sjoerg 
50827330f729Sjoerg   if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0),
50837330f729Sjoerg                                            ArgCount,
50847330f729Sjoerg                                            true /* CanIndexImplicitThis */))
50857330f729Sjoerg     return;
50867330f729Sjoerg 
50877330f729Sjoerg   // ArgCount isn't a parameter index [0;n), it's a count [1;n]
50887330f729Sjoerg   D->addAttr(::new (S.Context)
50897330f729Sjoerg                  XRayLogArgsAttr(S.Context, AL, ArgCount.getSourceIndex()));
50907330f729Sjoerg }
50917330f729Sjoerg 
handlePatchableFunctionEntryAttr(Sema & S,Decl * D,const ParsedAttr & AL)5092*e038c9c4Sjoerg static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D,
5093*e038c9c4Sjoerg                                              const ParsedAttr &AL) {
5094*e038c9c4Sjoerg   uint32_t Count = 0, Offset = 0;
5095*e038c9c4Sjoerg   if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Count, 0, true))
5096*e038c9c4Sjoerg     return;
5097*e038c9c4Sjoerg   if (AL.getNumArgs() == 2) {
5098*e038c9c4Sjoerg     Expr *Arg = AL.getArgAsExpr(1);
5099*e038c9c4Sjoerg     if (!checkUInt32Argument(S, AL, Arg, Offset, 1, true))
5100*e038c9c4Sjoerg       return;
5101*e038c9c4Sjoerg     if (Count < Offset) {
5102*e038c9c4Sjoerg       S.Diag(getAttrLoc(AL), diag::err_attribute_argument_out_of_range)
5103*e038c9c4Sjoerg           << &AL << 0 << Count << Arg->getBeginLoc();
5104*e038c9c4Sjoerg       return;
51057330f729Sjoerg     }
51067330f729Sjoerg   }
5107*e038c9c4Sjoerg   D->addAttr(::new (S.Context)
5108*e038c9c4Sjoerg                  PatchableFunctionEntryAttr(S.Context, AL, Count, Offset));
5109*e038c9c4Sjoerg }
51107330f729Sjoerg 
5111*e038c9c4Sjoerg namespace {
5112*e038c9c4Sjoerg struct IntrinToName {
5113*e038c9c4Sjoerg   uint32_t Id;
5114*e038c9c4Sjoerg   int32_t FullName;
5115*e038c9c4Sjoerg   int32_t ShortName;
5116*e038c9c4Sjoerg };
5117*e038c9c4Sjoerg } // unnamed namespace
5118*e038c9c4Sjoerg 
ArmBuiltinAliasValid(unsigned BuiltinID,StringRef AliasName,ArrayRef<IntrinToName> Map,const char * IntrinNames)5119*e038c9c4Sjoerg static bool ArmBuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
5120*e038c9c4Sjoerg                                  ArrayRef<IntrinToName> Map,
5121*e038c9c4Sjoerg                                  const char *IntrinNames) {
5122*e038c9c4Sjoerg   if (AliasName.startswith("__arm_"))
5123*e038c9c4Sjoerg     AliasName = AliasName.substr(6);
5124*e038c9c4Sjoerg   const IntrinToName *It = std::lower_bound(
5125*e038c9c4Sjoerg       Map.begin(), Map.end(), BuiltinID,
5126*e038c9c4Sjoerg       [](const IntrinToName &L, unsigned Id) { return L.Id < Id; });
5127*e038c9c4Sjoerg   if (It == Map.end() || It->Id != BuiltinID)
5128*e038c9c4Sjoerg     return false;
5129*e038c9c4Sjoerg   StringRef FullName(&IntrinNames[It->FullName]);
5130*e038c9c4Sjoerg   if (AliasName == FullName)
5131*e038c9c4Sjoerg     return true;
5132*e038c9c4Sjoerg   if (It->ShortName == -1)
5133*e038c9c4Sjoerg     return false;
5134*e038c9c4Sjoerg   StringRef ShortName(&IntrinNames[It->ShortName]);
5135*e038c9c4Sjoerg   return AliasName == ShortName;
5136*e038c9c4Sjoerg }
5137*e038c9c4Sjoerg 
ArmMveAliasValid(unsigned BuiltinID,StringRef AliasName)5138*e038c9c4Sjoerg static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) {
5139*e038c9c4Sjoerg #include "clang/Basic/arm_mve_builtin_aliases.inc"
5140*e038c9c4Sjoerg   // The included file defines:
5141*e038c9c4Sjoerg   // - ArrayRef<IntrinToName> Map
5142*e038c9c4Sjoerg   // - const char IntrinNames[]
5143*e038c9c4Sjoerg   return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
5144*e038c9c4Sjoerg }
5145*e038c9c4Sjoerg 
ArmCdeAliasValid(unsigned BuiltinID,StringRef AliasName)5146*e038c9c4Sjoerg static bool ArmCdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
5147*e038c9c4Sjoerg #include "clang/Basic/arm_cde_builtin_aliases.inc"
5148*e038c9c4Sjoerg   return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
5149*e038c9c4Sjoerg }
5150*e038c9c4Sjoerg 
ArmSveAliasValid(unsigned BuiltinID,StringRef AliasName)5151*e038c9c4Sjoerg static bool ArmSveAliasValid(unsigned BuiltinID, StringRef AliasName) {
5152*e038c9c4Sjoerg   return BuiltinID >= AArch64::FirstSVEBuiltin &&
5153*e038c9c4Sjoerg          BuiltinID <= AArch64::LastSVEBuiltin;
5154*e038c9c4Sjoerg }
5155*e038c9c4Sjoerg 
handleArmBuiltinAliasAttr(Sema & S,Decl * D,const ParsedAttr & AL)5156*e038c9c4Sjoerg static void handleArmBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
51577330f729Sjoerg   if (!AL.isArgIdent(0)) {
51587330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
51597330f729Sjoerg         << AL << 1 << AANT_ArgumentIdentifier;
51607330f729Sjoerg     return;
51617330f729Sjoerg   }
51627330f729Sjoerg 
51637330f729Sjoerg   IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
51647330f729Sjoerg   unsigned BuiltinID = Ident->getBuiltinID();
5165*e038c9c4Sjoerg   StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
51667330f729Sjoerg 
5167*e038c9c4Sjoerg   bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
5168*e038c9c4Sjoerg   if ((IsAArch64 && !ArmSveAliasValid(BuiltinID, AliasName)) ||
5169*e038c9c4Sjoerg       (!IsAArch64 && !ArmMveAliasValid(BuiltinID, AliasName) &&
5170*e038c9c4Sjoerg        !ArmCdeAliasValid(BuiltinID, AliasName))) {
5171*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
51727330f729Sjoerg     return;
51737330f729Sjoerg   }
51747330f729Sjoerg 
5175*e038c9c4Sjoerg   D->addAttr(::new (S.Context) ArmBuiltinAliasAttr(S.Context, AL, Ident));
5176*e038c9c4Sjoerg }
5177*e038c9c4Sjoerg 
RISCVAliasValid(unsigned BuiltinID,StringRef AliasName)5178*e038c9c4Sjoerg static bool RISCVAliasValid(unsigned BuiltinID, StringRef AliasName) {
5179*e038c9c4Sjoerg   return BuiltinID >= Builtin::FirstTSBuiltin &&
5180*e038c9c4Sjoerg          BuiltinID < RISCV::LastTSBuiltin;
5181*e038c9c4Sjoerg }
5182*e038c9c4Sjoerg 
handleBuiltinAliasAttr(Sema & S,Decl * D,const ParsedAttr & AL)5183*e038c9c4Sjoerg static void handleBuiltinAliasAttr(Sema &S, Decl *D,
5184*e038c9c4Sjoerg                                         const ParsedAttr &AL) {
5185*e038c9c4Sjoerg   if (!AL.isArgIdent(0)) {
5186*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
5187*e038c9c4Sjoerg         << AL << 1 << AANT_ArgumentIdentifier;
5188*e038c9c4Sjoerg     return;
5189*e038c9c4Sjoerg   }
5190*e038c9c4Sjoerg 
5191*e038c9c4Sjoerg   IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
5192*e038c9c4Sjoerg   unsigned BuiltinID = Ident->getBuiltinID();
5193*e038c9c4Sjoerg   StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
5194*e038c9c4Sjoerg 
5195*e038c9c4Sjoerg   bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
5196*e038c9c4Sjoerg   bool IsARM = S.Context.getTargetInfo().getTriple().isARM();
5197*e038c9c4Sjoerg   bool IsRISCV = S.Context.getTargetInfo().getTriple().isRISCV();
5198*e038c9c4Sjoerg   if ((IsAArch64 && !ArmSveAliasValid(BuiltinID, AliasName)) ||
5199*e038c9c4Sjoerg       (IsARM && !ArmMveAliasValid(BuiltinID, AliasName) &&
5200*e038c9c4Sjoerg        !ArmCdeAliasValid(BuiltinID, AliasName)) ||
5201*e038c9c4Sjoerg       (IsRISCV && !RISCVAliasValid(BuiltinID, AliasName)) ||
5202*e038c9c4Sjoerg       (!IsAArch64 && !IsARM && !IsRISCV)) {
5203*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_builtin_alias) << AL;
5204*e038c9c4Sjoerg     return;
5205*e038c9c4Sjoerg   }
5206*e038c9c4Sjoerg 
5207*e038c9c4Sjoerg   D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident));
52087330f729Sjoerg }
52097330f729Sjoerg 
52107330f729Sjoerg //===----------------------------------------------------------------------===//
52117330f729Sjoerg // Checker-specific attribute handlers.
52127330f729Sjoerg //===----------------------------------------------------------------------===//
isValidSubjectOfNSReturnsRetainedAttribute(QualType QT)52137330f729Sjoerg static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {
52147330f729Sjoerg   return QT->isDependentType() || QT->isObjCRetainableType();
52157330f729Sjoerg }
52167330f729Sjoerg 
isValidSubjectOfNSAttribute(QualType QT)52177330f729Sjoerg static bool isValidSubjectOfNSAttribute(QualType QT) {
52187330f729Sjoerg   return QT->isDependentType() || QT->isObjCObjectPointerType() ||
52197330f729Sjoerg          QT->isObjCNSObjectType();
52207330f729Sjoerg }
52217330f729Sjoerg 
isValidSubjectOfCFAttribute(QualType QT)52227330f729Sjoerg static bool isValidSubjectOfCFAttribute(QualType QT) {
52237330f729Sjoerg   return QT->isDependentType() || QT->isPointerType() ||
52247330f729Sjoerg          isValidSubjectOfNSAttribute(QT);
52257330f729Sjoerg }
52267330f729Sjoerg 
isValidSubjectOfOSAttribute(QualType QT)52277330f729Sjoerg static bool isValidSubjectOfOSAttribute(QualType QT) {
52287330f729Sjoerg   if (QT->isDependentType())
52297330f729Sjoerg     return true;
52307330f729Sjoerg   QualType PT = QT->getPointeeType();
52317330f729Sjoerg   return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr;
52327330f729Sjoerg }
52337330f729Sjoerg 
AddXConsumedAttr(Decl * D,const AttributeCommonInfo & CI,RetainOwnershipKind K,bool IsTemplateInstantiation)52347330f729Sjoerg void Sema::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
52357330f729Sjoerg                             RetainOwnershipKind K,
52367330f729Sjoerg                             bool IsTemplateInstantiation) {
52377330f729Sjoerg   ValueDecl *VD = cast<ValueDecl>(D);
52387330f729Sjoerg   switch (K) {
52397330f729Sjoerg   case RetainOwnershipKind::OS:
52407330f729Sjoerg     handleSimpleAttributeOrDiagnose<OSConsumedAttr>(
52417330f729Sjoerg         *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()),
52427330f729Sjoerg         diag::warn_ns_attribute_wrong_parameter_type,
52437330f729Sjoerg         /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1);
52447330f729Sjoerg     return;
52457330f729Sjoerg   case RetainOwnershipKind::NS:
52467330f729Sjoerg     handleSimpleAttributeOrDiagnose<NSConsumedAttr>(
52477330f729Sjoerg         *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()),
52487330f729Sjoerg 
52497330f729Sjoerg         // These attributes are normally just advisory, but in ARC, ns_consumed
52507330f729Sjoerg         // is significant.  Allow non-dependent code to contain inappropriate
52517330f729Sjoerg         // attributes even in ARC, but require template instantiations to be
52527330f729Sjoerg         // set up correctly.
52537330f729Sjoerg         ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount)
52547330f729Sjoerg              ? diag::err_ns_attribute_wrong_parameter_type
52557330f729Sjoerg              : diag::warn_ns_attribute_wrong_parameter_type),
52567330f729Sjoerg         /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0);
52577330f729Sjoerg     return;
52587330f729Sjoerg   case RetainOwnershipKind::CF:
52597330f729Sjoerg     handleSimpleAttributeOrDiagnose<CFConsumedAttr>(
52607330f729Sjoerg         *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()),
52617330f729Sjoerg         diag::warn_ns_attribute_wrong_parameter_type,
52627330f729Sjoerg         /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1);
52637330f729Sjoerg     return;
52647330f729Sjoerg   }
52657330f729Sjoerg }
52667330f729Sjoerg 
52677330f729Sjoerg static Sema::RetainOwnershipKind
parsedAttrToRetainOwnershipKind(const ParsedAttr & AL)52687330f729Sjoerg parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) {
52697330f729Sjoerg   switch (AL.getKind()) {
52707330f729Sjoerg   case ParsedAttr::AT_CFConsumed:
52717330f729Sjoerg   case ParsedAttr::AT_CFReturnsRetained:
52727330f729Sjoerg   case ParsedAttr::AT_CFReturnsNotRetained:
52737330f729Sjoerg     return Sema::RetainOwnershipKind::CF;
52747330f729Sjoerg   case ParsedAttr::AT_OSConsumesThis:
52757330f729Sjoerg   case ParsedAttr::AT_OSConsumed:
52767330f729Sjoerg   case ParsedAttr::AT_OSReturnsRetained:
52777330f729Sjoerg   case ParsedAttr::AT_OSReturnsNotRetained:
52787330f729Sjoerg   case ParsedAttr::AT_OSReturnsRetainedOnZero:
52797330f729Sjoerg   case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
52807330f729Sjoerg     return Sema::RetainOwnershipKind::OS;
52817330f729Sjoerg   case ParsedAttr::AT_NSConsumesSelf:
52827330f729Sjoerg   case ParsedAttr::AT_NSConsumed:
52837330f729Sjoerg   case ParsedAttr::AT_NSReturnsRetained:
52847330f729Sjoerg   case ParsedAttr::AT_NSReturnsNotRetained:
52857330f729Sjoerg   case ParsedAttr::AT_NSReturnsAutoreleased:
52867330f729Sjoerg     return Sema::RetainOwnershipKind::NS;
52877330f729Sjoerg   default:
52887330f729Sjoerg     llvm_unreachable("Wrong argument supplied");
52897330f729Sjoerg   }
52907330f729Sjoerg }
52917330f729Sjoerg 
checkNSReturnsRetainedReturnType(SourceLocation Loc,QualType QT)52927330f729Sjoerg bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) {
52937330f729Sjoerg   if (isValidSubjectOfNSReturnsRetainedAttribute(QT))
52947330f729Sjoerg     return false;
52957330f729Sjoerg 
52967330f729Sjoerg   Diag(Loc, diag::warn_ns_attribute_wrong_return_type)
52977330f729Sjoerg       << "'ns_returns_retained'" << 0 << 0;
52987330f729Sjoerg   return true;
52997330f729Sjoerg }
53007330f729Sjoerg 
53017330f729Sjoerg /// \return whether the parameter is a pointer to OSObject pointer.
isValidOSObjectOutParameter(const Decl * D)53027330f729Sjoerg static bool isValidOSObjectOutParameter(const Decl *D) {
53037330f729Sjoerg   const auto *PVD = dyn_cast<ParmVarDecl>(D);
53047330f729Sjoerg   if (!PVD)
53057330f729Sjoerg     return false;
53067330f729Sjoerg   QualType QT = PVD->getType();
53077330f729Sjoerg   QualType PT = QT->getPointeeType();
53087330f729Sjoerg   return !PT.isNull() && isValidSubjectOfOSAttribute(PT);
53097330f729Sjoerg }
53107330f729Sjoerg 
handleXReturnsXRetainedAttr(Sema & S,Decl * D,const ParsedAttr & AL)53117330f729Sjoerg static void handleXReturnsXRetainedAttr(Sema &S, Decl *D,
53127330f729Sjoerg                                         const ParsedAttr &AL) {
53137330f729Sjoerg   QualType ReturnType;
53147330f729Sjoerg   Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);
53157330f729Sjoerg 
53167330f729Sjoerg   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
53177330f729Sjoerg     ReturnType = MD->getReturnType();
53187330f729Sjoerg   } else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
53197330f729Sjoerg              (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) {
53207330f729Sjoerg     return; // ignore: was handled as a type attribute
53217330f729Sjoerg   } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
53227330f729Sjoerg     ReturnType = PD->getType();
53237330f729Sjoerg   } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
53247330f729Sjoerg     ReturnType = FD->getReturnType();
53257330f729Sjoerg   } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
53267330f729Sjoerg     // Attributes on parameters are used for out-parameters,
53277330f729Sjoerg     // passed as pointers-to-pointers.
53287330f729Sjoerg     unsigned DiagID = K == Sema::RetainOwnershipKind::CF
53297330f729Sjoerg             ? /*pointer-to-CF-pointer*/2
53307330f729Sjoerg             : /*pointer-to-OSObject-pointer*/3;
53317330f729Sjoerg     ReturnType = Param->getType()->getPointeeType();
53327330f729Sjoerg     if (ReturnType.isNull()) {
53337330f729Sjoerg       S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
53347330f729Sjoerg           << AL << DiagID << AL.getRange();
53357330f729Sjoerg       return;
53367330f729Sjoerg     }
53377330f729Sjoerg   } else if (AL.isUsedAsTypeAttr()) {
53387330f729Sjoerg     return;
53397330f729Sjoerg   } else {
53407330f729Sjoerg     AttributeDeclKind ExpectedDeclKind;
53417330f729Sjoerg     switch (AL.getKind()) {
53427330f729Sjoerg     default: llvm_unreachable("invalid ownership attribute");
53437330f729Sjoerg     case ParsedAttr::AT_NSReturnsRetained:
53447330f729Sjoerg     case ParsedAttr::AT_NSReturnsAutoreleased:
53457330f729Sjoerg     case ParsedAttr::AT_NSReturnsNotRetained:
53467330f729Sjoerg       ExpectedDeclKind = ExpectedFunctionOrMethod;
53477330f729Sjoerg       break;
53487330f729Sjoerg 
53497330f729Sjoerg     case ParsedAttr::AT_OSReturnsRetained:
53507330f729Sjoerg     case ParsedAttr::AT_OSReturnsNotRetained:
53517330f729Sjoerg     case ParsedAttr::AT_CFReturnsRetained:
53527330f729Sjoerg     case ParsedAttr::AT_CFReturnsNotRetained:
53537330f729Sjoerg       ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
53547330f729Sjoerg       break;
53557330f729Sjoerg     }
53567330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type)
53577330f729Sjoerg         << AL.getRange() << AL << ExpectedDeclKind;
53587330f729Sjoerg     return;
53597330f729Sjoerg   }
53607330f729Sjoerg 
53617330f729Sjoerg   bool TypeOK;
53627330f729Sjoerg   bool Cf;
53637330f729Sjoerg   unsigned ParmDiagID = 2; // Pointer-to-CF-pointer
53647330f729Sjoerg   switch (AL.getKind()) {
53657330f729Sjoerg   default: llvm_unreachable("invalid ownership attribute");
53667330f729Sjoerg   case ParsedAttr::AT_NSReturnsRetained:
53677330f729Sjoerg     TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);
53687330f729Sjoerg     Cf = false;
53697330f729Sjoerg     break;
53707330f729Sjoerg 
53717330f729Sjoerg   case ParsedAttr::AT_NSReturnsAutoreleased:
53727330f729Sjoerg   case ParsedAttr::AT_NSReturnsNotRetained:
53737330f729Sjoerg     TypeOK = isValidSubjectOfNSAttribute(ReturnType);
53747330f729Sjoerg     Cf = false;
53757330f729Sjoerg     break;
53767330f729Sjoerg 
53777330f729Sjoerg   case ParsedAttr::AT_CFReturnsRetained:
53787330f729Sjoerg   case ParsedAttr::AT_CFReturnsNotRetained:
53797330f729Sjoerg     TypeOK = isValidSubjectOfCFAttribute(ReturnType);
53807330f729Sjoerg     Cf = true;
53817330f729Sjoerg     break;
53827330f729Sjoerg 
53837330f729Sjoerg   case ParsedAttr::AT_OSReturnsRetained:
53847330f729Sjoerg   case ParsedAttr::AT_OSReturnsNotRetained:
53857330f729Sjoerg     TypeOK = isValidSubjectOfOSAttribute(ReturnType);
53867330f729Sjoerg     Cf = true;
53877330f729Sjoerg     ParmDiagID = 3; // Pointer-to-OSObject-pointer
53887330f729Sjoerg     break;
53897330f729Sjoerg   }
53907330f729Sjoerg 
53917330f729Sjoerg   if (!TypeOK) {
53927330f729Sjoerg     if (AL.isUsedAsTypeAttr())
53937330f729Sjoerg       return;
53947330f729Sjoerg 
53957330f729Sjoerg     if (isa<ParmVarDecl>(D)) {
53967330f729Sjoerg       S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
53977330f729Sjoerg           << AL << ParmDiagID << AL.getRange();
53987330f729Sjoerg     } else {
53997330f729Sjoerg       // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
54007330f729Sjoerg       enum : unsigned {
54017330f729Sjoerg         Function,
54027330f729Sjoerg         Method,
54037330f729Sjoerg         Property
54047330f729Sjoerg       } SubjectKind = Function;
54057330f729Sjoerg       if (isa<ObjCMethodDecl>(D))
54067330f729Sjoerg         SubjectKind = Method;
54077330f729Sjoerg       else if (isa<ObjCPropertyDecl>(D))
54087330f729Sjoerg         SubjectKind = Property;
54097330f729Sjoerg       S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
54107330f729Sjoerg           << AL << SubjectKind << Cf << AL.getRange();
54117330f729Sjoerg     }
54127330f729Sjoerg     return;
54137330f729Sjoerg   }
54147330f729Sjoerg 
54157330f729Sjoerg   switch (AL.getKind()) {
54167330f729Sjoerg     default:
54177330f729Sjoerg       llvm_unreachable("invalid ownership attribute");
54187330f729Sjoerg     case ParsedAttr::AT_NSReturnsAutoreleased:
54197330f729Sjoerg       handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL);
54207330f729Sjoerg       return;
54217330f729Sjoerg     case ParsedAttr::AT_CFReturnsNotRetained:
54227330f729Sjoerg       handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL);
54237330f729Sjoerg       return;
54247330f729Sjoerg     case ParsedAttr::AT_NSReturnsNotRetained:
54257330f729Sjoerg       handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL);
54267330f729Sjoerg       return;
54277330f729Sjoerg     case ParsedAttr::AT_CFReturnsRetained:
54287330f729Sjoerg       handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL);
54297330f729Sjoerg       return;
54307330f729Sjoerg     case ParsedAttr::AT_NSReturnsRetained:
54317330f729Sjoerg       handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL);
54327330f729Sjoerg       return;
54337330f729Sjoerg     case ParsedAttr::AT_OSReturnsRetained:
54347330f729Sjoerg       handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL);
54357330f729Sjoerg       return;
54367330f729Sjoerg     case ParsedAttr::AT_OSReturnsNotRetained:
54377330f729Sjoerg       handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL);
54387330f729Sjoerg       return;
54397330f729Sjoerg   };
54407330f729Sjoerg }
54417330f729Sjoerg 
handleObjCReturnsInnerPointerAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)54427330f729Sjoerg static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
54437330f729Sjoerg                                               const ParsedAttr &Attrs) {
54447330f729Sjoerg   const int EP_ObjCMethod = 1;
54457330f729Sjoerg   const int EP_ObjCProperty = 2;
54467330f729Sjoerg 
54477330f729Sjoerg   SourceLocation loc = Attrs.getLoc();
54487330f729Sjoerg   QualType resultType;
54497330f729Sjoerg   if (isa<ObjCMethodDecl>(D))
54507330f729Sjoerg     resultType = cast<ObjCMethodDecl>(D)->getReturnType();
54517330f729Sjoerg   else
54527330f729Sjoerg     resultType = cast<ObjCPropertyDecl>(D)->getType();
54537330f729Sjoerg 
54547330f729Sjoerg   if (!resultType->isReferenceType() &&
54557330f729Sjoerg       (!resultType->isPointerType() || resultType->isObjCRetainableType())) {
54567330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
54577330f729Sjoerg         << SourceRange(loc) << Attrs
54587330f729Sjoerg         << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
54597330f729Sjoerg         << /*non-retainable pointer*/ 2;
54607330f729Sjoerg 
54617330f729Sjoerg     // Drop the attribute.
54627330f729Sjoerg     return;
54637330f729Sjoerg   }
54647330f729Sjoerg 
54657330f729Sjoerg   D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(S.Context, Attrs));
54667330f729Sjoerg }
54677330f729Sjoerg 
handleObjCRequiresSuperAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)54687330f729Sjoerg static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
54697330f729Sjoerg                                         const ParsedAttr &Attrs) {
54707330f729Sjoerg   const auto *Method = cast<ObjCMethodDecl>(D);
54717330f729Sjoerg 
54727330f729Sjoerg   const DeclContext *DC = Method->getDeclContext();
54737330f729Sjoerg   if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
54747330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
54757330f729Sjoerg                                                                       << 0;
54767330f729Sjoerg     S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
54777330f729Sjoerg     return;
54787330f729Sjoerg   }
54797330f729Sjoerg   if (Method->getMethodFamily() == OMF_dealloc) {
54807330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
54817330f729Sjoerg                                                                       << 1;
54827330f729Sjoerg     return;
54837330f729Sjoerg   }
54847330f729Sjoerg 
54857330f729Sjoerg   D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
54867330f729Sjoerg }
54877330f729Sjoerg 
handleNSErrorDomain(Sema & S,Decl * D,const ParsedAttr & AL)5488*e038c9c4Sjoerg static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
5489*e038c9c4Sjoerg   auto *E = AL.getArgAsExpr(0);
5490*e038c9c4Sjoerg   auto Loc = E ? E->getBeginLoc() : AL.getLoc();
5491*e038c9c4Sjoerg 
5492*e038c9c4Sjoerg   auto *DRE = dyn_cast<DeclRefExpr>(AL.getArgAsExpr(0));
5493*e038c9c4Sjoerg   if (!DRE) {
5494*e038c9c4Sjoerg     S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
5495*e038c9c4Sjoerg     return;
5496*e038c9c4Sjoerg   }
5497*e038c9c4Sjoerg 
5498*e038c9c4Sjoerg   auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
5499*e038c9c4Sjoerg   if (!VD) {
5500*e038c9c4Sjoerg     S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
5501*e038c9c4Sjoerg     return;
5502*e038c9c4Sjoerg   }
5503*e038c9c4Sjoerg 
5504*e038c9c4Sjoerg   if (!isNSStringType(VD->getType(), S.Context) &&
5505*e038c9c4Sjoerg       !isCFStringType(VD->getType(), S.Context)) {
5506*e038c9c4Sjoerg     S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
5507*e038c9c4Sjoerg     return;
5508*e038c9c4Sjoerg   }
5509*e038c9c4Sjoerg 
5510*e038c9c4Sjoerg   D->addAttr(::new (S.Context) NSErrorDomainAttr(S.Context, AL, VD));
5511*e038c9c4Sjoerg }
5512*e038c9c4Sjoerg 
handleObjCBridgeAttr(Sema & S,Decl * D,const ParsedAttr & AL)55137330f729Sjoerg static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
55147330f729Sjoerg   IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
55157330f729Sjoerg 
55167330f729Sjoerg   if (!Parm) {
55177330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
55187330f729Sjoerg     return;
55197330f729Sjoerg   }
55207330f729Sjoerg 
55217330f729Sjoerg   // Typedefs only allow objc_bridge(id) and have some additional checking.
55227330f729Sjoerg   if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
55237330f729Sjoerg     if (!Parm->Ident->isStr("id")) {
55247330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL;
55257330f729Sjoerg       return;
55267330f729Sjoerg     }
55277330f729Sjoerg 
55287330f729Sjoerg     // Only allow 'cv void *'.
55297330f729Sjoerg     QualType T = TD->getUnderlyingType();
55307330f729Sjoerg     if (!T->isVoidPointerType()) {
55317330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
55327330f729Sjoerg       return;
55337330f729Sjoerg     }
55347330f729Sjoerg   }
55357330f729Sjoerg 
55367330f729Sjoerg   D->addAttr(::new (S.Context) ObjCBridgeAttr(S.Context, AL, Parm->Ident));
55377330f729Sjoerg }
55387330f729Sjoerg 
handleObjCBridgeMutableAttr(Sema & S,Decl * D,const ParsedAttr & AL)55397330f729Sjoerg static void handleObjCBridgeMutableAttr(Sema &S, Decl *D,
55407330f729Sjoerg                                         const ParsedAttr &AL) {
55417330f729Sjoerg   IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
55427330f729Sjoerg 
55437330f729Sjoerg   if (!Parm) {
55447330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
55457330f729Sjoerg     return;
55467330f729Sjoerg   }
55477330f729Sjoerg 
55487330f729Sjoerg   D->addAttr(::new (S.Context)
55497330f729Sjoerg                  ObjCBridgeMutableAttr(S.Context, AL, Parm->Ident));
55507330f729Sjoerg }
55517330f729Sjoerg 
handleObjCBridgeRelatedAttr(Sema & S,Decl * D,const ParsedAttr & AL)55527330f729Sjoerg static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D,
55537330f729Sjoerg                                         const ParsedAttr &AL) {
55547330f729Sjoerg   IdentifierInfo *RelatedClass =
55557330f729Sjoerg       AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr;
55567330f729Sjoerg   if (!RelatedClass) {
55577330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
55587330f729Sjoerg     return;
55597330f729Sjoerg   }
55607330f729Sjoerg   IdentifierInfo *ClassMethod =
55617330f729Sjoerg     AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
55627330f729Sjoerg   IdentifierInfo *InstanceMethod =
55637330f729Sjoerg     AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
55647330f729Sjoerg   D->addAttr(::new (S.Context) ObjCBridgeRelatedAttr(
55657330f729Sjoerg       S.Context, AL, RelatedClass, ClassMethod, InstanceMethod));
55667330f729Sjoerg }
55677330f729Sjoerg 
handleObjCDesignatedInitializer(Sema & S,Decl * D,const ParsedAttr & AL)55687330f729Sjoerg static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
55697330f729Sjoerg                                             const ParsedAttr &AL) {
55707330f729Sjoerg   DeclContext *Ctx = D->getDeclContext();
55717330f729Sjoerg 
55727330f729Sjoerg   // This attribute can only be applied to methods in interfaces or class
55737330f729Sjoerg   // extensions.
55747330f729Sjoerg   if (!isa<ObjCInterfaceDecl>(Ctx) &&
55757330f729Sjoerg       !(isa<ObjCCategoryDecl>(Ctx) &&
55767330f729Sjoerg         cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) {
55777330f729Sjoerg     S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
55787330f729Sjoerg     return;
55797330f729Sjoerg   }
55807330f729Sjoerg 
55817330f729Sjoerg   ObjCInterfaceDecl *IFace;
55827330f729Sjoerg   if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx))
55837330f729Sjoerg     IFace = CatDecl->getClassInterface();
55847330f729Sjoerg   else
55857330f729Sjoerg     IFace = cast<ObjCInterfaceDecl>(Ctx);
55867330f729Sjoerg 
55877330f729Sjoerg   if (!IFace)
55887330f729Sjoerg     return;
55897330f729Sjoerg 
55907330f729Sjoerg   IFace->setHasDesignatedInitializers();
55917330f729Sjoerg   D->addAttr(::new (S.Context) ObjCDesignatedInitializerAttr(S.Context, AL));
55927330f729Sjoerg }
55937330f729Sjoerg 
handleObjCRuntimeName(Sema & S,Decl * D,const ParsedAttr & AL)55947330f729Sjoerg static void handleObjCRuntimeName(Sema &S, Decl *D, const ParsedAttr &AL) {
55957330f729Sjoerg   StringRef MetaDataName;
55967330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, MetaDataName))
55977330f729Sjoerg     return;
55987330f729Sjoerg   D->addAttr(::new (S.Context)
55997330f729Sjoerg                  ObjCRuntimeNameAttr(S.Context, AL, MetaDataName));
56007330f729Sjoerg }
56017330f729Sjoerg 
56027330f729Sjoerg // When a user wants to use objc_boxable with a union or struct
56037330f729Sjoerg // but they don't have access to the declaration (legacy/third-party code)
56047330f729Sjoerg // then they can 'enable' this feature with a typedef:
56057330f729Sjoerg // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
handleObjCBoxable(Sema & S,Decl * D,const ParsedAttr & AL)56067330f729Sjoerg static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) {
56077330f729Sjoerg   bool notify = false;
56087330f729Sjoerg 
56097330f729Sjoerg   auto *RD = dyn_cast<RecordDecl>(D);
56107330f729Sjoerg   if (RD && RD->getDefinition()) {
56117330f729Sjoerg     RD = RD->getDefinition();
56127330f729Sjoerg     notify = true;
56137330f729Sjoerg   }
56147330f729Sjoerg 
56157330f729Sjoerg   if (RD) {
56167330f729Sjoerg     ObjCBoxableAttr *BoxableAttr =
56177330f729Sjoerg         ::new (S.Context) ObjCBoxableAttr(S.Context, AL);
56187330f729Sjoerg     RD->addAttr(BoxableAttr);
56197330f729Sjoerg     if (notify) {
56207330f729Sjoerg       // we need to notify ASTReader/ASTWriter about
56217330f729Sjoerg       // modification of existing declaration
56227330f729Sjoerg       if (ASTMutationListener *L = S.getASTMutationListener())
56237330f729Sjoerg         L->AddedAttributeToRecord(BoxableAttr, RD);
56247330f729Sjoerg     }
56257330f729Sjoerg   }
56267330f729Sjoerg }
56277330f729Sjoerg 
handleObjCOwnershipAttr(Sema & S,Decl * D,const ParsedAttr & AL)56287330f729Sjoerg static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
56297330f729Sjoerg   if (hasDeclarator(D)) return;
56307330f729Sjoerg 
56317330f729Sjoerg   S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)
56327330f729Sjoerg       << AL.getRange() << AL << ExpectedVariable;
56337330f729Sjoerg }
56347330f729Sjoerg 
handleObjCPreciseLifetimeAttr(Sema & S,Decl * D,const ParsedAttr & AL)56357330f729Sjoerg static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
56367330f729Sjoerg                                           const ParsedAttr &AL) {
56377330f729Sjoerg   const auto *VD = cast<ValueDecl>(D);
56387330f729Sjoerg   QualType QT = VD->getType();
56397330f729Sjoerg 
56407330f729Sjoerg   if (!QT->isDependentType() &&
56417330f729Sjoerg       !QT->isObjCLifetimeType()) {
56427330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type)
56437330f729Sjoerg       << QT;
56447330f729Sjoerg     return;
56457330f729Sjoerg   }
56467330f729Sjoerg 
56477330f729Sjoerg   Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime();
56487330f729Sjoerg 
56497330f729Sjoerg   // If we have no lifetime yet, check the lifetime we're presumably
56507330f729Sjoerg   // going to infer.
56517330f729Sjoerg   if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType())
56527330f729Sjoerg     Lifetime = QT->getObjCARCImplicitLifetime();
56537330f729Sjoerg 
56547330f729Sjoerg   switch (Lifetime) {
56557330f729Sjoerg   case Qualifiers::OCL_None:
56567330f729Sjoerg     assert(QT->isDependentType() &&
56577330f729Sjoerg            "didn't infer lifetime for non-dependent type?");
56587330f729Sjoerg     break;
56597330f729Sjoerg 
56607330f729Sjoerg   case Qualifiers::OCL_Weak:   // meaningful
56617330f729Sjoerg   case Qualifiers::OCL_Strong: // meaningful
56627330f729Sjoerg     break;
56637330f729Sjoerg 
56647330f729Sjoerg   case Qualifiers::OCL_ExplicitNone:
56657330f729Sjoerg   case Qualifiers::OCL_Autoreleasing:
56667330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
56677330f729Sjoerg         << (Lifetime == Qualifiers::OCL_Autoreleasing);
56687330f729Sjoerg     break;
56697330f729Sjoerg   }
56707330f729Sjoerg 
56717330f729Sjoerg   D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL));
56727330f729Sjoerg }
56737330f729Sjoerg 
handleSwiftAttrAttr(Sema & S,Decl * D,const ParsedAttr & AL)5674*e038c9c4Sjoerg static void handleSwiftAttrAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5675*e038c9c4Sjoerg   // Make sure that there is a string literal as the annotation's single
5676*e038c9c4Sjoerg   // argument.
5677*e038c9c4Sjoerg   StringRef Str;
5678*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
5679*e038c9c4Sjoerg     return;
5680*e038c9c4Sjoerg 
5681*e038c9c4Sjoerg   D->addAttr(::new (S.Context) SwiftAttrAttr(S.Context, AL, Str));
5682*e038c9c4Sjoerg }
5683*e038c9c4Sjoerg 
handleSwiftBridge(Sema & S,Decl * D,const ParsedAttr & AL)5684*e038c9c4Sjoerg static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) {
5685*e038c9c4Sjoerg   // Make sure that there is a string literal as the annotation's single
5686*e038c9c4Sjoerg   // argument.
5687*e038c9c4Sjoerg   StringRef BT;
5688*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, BT))
5689*e038c9c4Sjoerg     return;
5690*e038c9c4Sjoerg 
5691*e038c9c4Sjoerg   // Warn about duplicate attributes if they have different arguments, but drop
5692*e038c9c4Sjoerg   // any duplicate attributes regardless.
5693*e038c9c4Sjoerg   if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) {
5694*e038c9c4Sjoerg     if (Other->getSwiftType() != BT)
5695*e038c9c4Sjoerg       S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
5696*e038c9c4Sjoerg     return;
5697*e038c9c4Sjoerg   }
5698*e038c9c4Sjoerg 
5699*e038c9c4Sjoerg   D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT));
5700*e038c9c4Sjoerg }
5701*e038c9c4Sjoerg 
isErrorParameter(Sema & S,QualType QT)5702*e038c9c4Sjoerg static bool isErrorParameter(Sema &S, QualType QT) {
5703*e038c9c4Sjoerg   const auto *PT = QT->getAs<PointerType>();
5704*e038c9c4Sjoerg   if (!PT)
5705*e038c9c4Sjoerg     return false;
5706*e038c9c4Sjoerg 
5707*e038c9c4Sjoerg   QualType Pointee = PT->getPointeeType();
5708*e038c9c4Sjoerg 
5709*e038c9c4Sjoerg   // Check for NSError**.
5710*e038c9c4Sjoerg   if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>())
5711*e038c9c4Sjoerg     if (const auto *ID = OPT->getInterfaceDecl())
5712*e038c9c4Sjoerg       if (ID->getIdentifier() == S.getNSErrorIdent())
5713*e038c9c4Sjoerg         return true;
5714*e038c9c4Sjoerg 
5715*e038c9c4Sjoerg   // Check for CFError**.
5716*e038c9c4Sjoerg   if (const auto *PT = Pointee->getAs<PointerType>())
5717*e038c9c4Sjoerg     if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
5718*e038c9c4Sjoerg       if (S.isCFError(RT->getDecl()))
5719*e038c9c4Sjoerg         return true;
5720*e038c9c4Sjoerg 
5721*e038c9c4Sjoerg   return false;
5722*e038c9c4Sjoerg }
5723*e038c9c4Sjoerg 
handleSwiftError(Sema & S,Decl * D,const ParsedAttr & AL)5724*e038c9c4Sjoerg static void handleSwiftError(Sema &S, Decl *D, const ParsedAttr &AL) {
5725*e038c9c4Sjoerg   auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
5726*e038c9c4Sjoerg     for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
5727*e038c9c4Sjoerg       if (isErrorParameter(S, getFunctionOrMethodParamType(D, I)))
5728*e038c9c4Sjoerg         return true;
5729*e038c9c4Sjoerg     }
5730*e038c9c4Sjoerg 
5731*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
5732*e038c9c4Sjoerg         << AL << isa<ObjCMethodDecl>(D);
5733*e038c9c4Sjoerg     return false;
5734*e038c9c4Sjoerg   };
5735*e038c9c4Sjoerg 
5736*e038c9c4Sjoerg   auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
5737*e038c9c4Sjoerg     // - C, ObjC, and block pointers are definitely okay.
5738*e038c9c4Sjoerg     // - References are definitely not okay.
5739*e038c9c4Sjoerg     // - nullptr_t is weird, but acceptable.
5740*e038c9c4Sjoerg     QualType RT = getFunctionOrMethodResultType(D);
5741*e038c9c4Sjoerg     if (RT->hasPointerRepresentation() && !RT->isReferenceType())
5742*e038c9c4Sjoerg       return true;
5743*e038c9c4Sjoerg 
5744*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
5745*e038c9c4Sjoerg         << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
5746*e038c9c4Sjoerg         << /*pointer*/ 1;
5747*e038c9c4Sjoerg     return false;
5748*e038c9c4Sjoerg   };
5749*e038c9c4Sjoerg 
5750*e038c9c4Sjoerg   auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
5751*e038c9c4Sjoerg     QualType RT = getFunctionOrMethodResultType(D);
5752*e038c9c4Sjoerg     if (RT->isIntegralType(S.Context))
5753*e038c9c4Sjoerg       return true;
5754*e038c9c4Sjoerg 
5755*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
5756*e038c9c4Sjoerg         << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
5757*e038c9c4Sjoerg         << /*integral*/ 0;
5758*e038c9c4Sjoerg     return false;
5759*e038c9c4Sjoerg   };
5760*e038c9c4Sjoerg 
5761*e038c9c4Sjoerg   if (D->isInvalidDecl())
5762*e038c9c4Sjoerg     return;
5763*e038c9c4Sjoerg 
5764*e038c9c4Sjoerg   IdentifierLoc *Loc = AL.getArgAsIdent(0);
5765*e038c9c4Sjoerg   SwiftErrorAttr::ConventionKind Convention;
5766*e038c9c4Sjoerg   if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(),
5767*e038c9c4Sjoerg                                                   Convention)) {
5768*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
5769*e038c9c4Sjoerg         << AL << Loc->Ident;
5770*e038c9c4Sjoerg     return;
5771*e038c9c4Sjoerg   }
5772*e038c9c4Sjoerg 
5773*e038c9c4Sjoerg   switch (Convention) {
5774*e038c9c4Sjoerg   case SwiftErrorAttr::None:
5775*e038c9c4Sjoerg     // No additional validation required.
5776*e038c9c4Sjoerg     break;
5777*e038c9c4Sjoerg 
5778*e038c9c4Sjoerg   case SwiftErrorAttr::NonNullError:
5779*e038c9c4Sjoerg     if (!hasErrorParameter(S, D, AL))
5780*e038c9c4Sjoerg       return;
5781*e038c9c4Sjoerg     break;
5782*e038c9c4Sjoerg 
5783*e038c9c4Sjoerg   case SwiftErrorAttr::NullResult:
5784*e038c9c4Sjoerg     if (!hasErrorParameter(S, D, AL) || !hasPointerResult(S, D, AL))
5785*e038c9c4Sjoerg       return;
5786*e038c9c4Sjoerg     break;
5787*e038c9c4Sjoerg 
5788*e038c9c4Sjoerg   case SwiftErrorAttr::NonZeroResult:
5789*e038c9c4Sjoerg   case SwiftErrorAttr::ZeroResult:
5790*e038c9c4Sjoerg     if (!hasErrorParameter(S, D, AL) || !hasIntegerResult(S, D, AL))
5791*e038c9c4Sjoerg       return;
5792*e038c9c4Sjoerg     break;
5793*e038c9c4Sjoerg   }
5794*e038c9c4Sjoerg 
5795*e038c9c4Sjoerg   D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention));
5796*e038c9c4Sjoerg }
5797*e038c9c4Sjoerg 
checkSwiftAsyncErrorBlock(Sema & S,Decl * D,const SwiftAsyncErrorAttr * ErrorAttr,const SwiftAsyncAttr * AsyncAttr)5798*e038c9c4Sjoerg static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D,
5799*e038c9c4Sjoerg                                       const SwiftAsyncErrorAttr *ErrorAttr,
5800*e038c9c4Sjoerg                                       const SwiftAsyncAttr *AsyncAttr) {
5801*e038c9c4Sjoerg   if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
5802*e038c9c4Sjoerg     if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
5803*e038c9c4Sjoerg       S.Diag(AsyncAttr->getLocation(),
5804*e038c9c4Sjoerg              diag::err_swift_async_error_without_swift_async)
5805*e038c9c4Sjoerg           << AsyncAttr << isa<ObjCMethodDecl>(D);
5806*e038c9c4Sjoerg     }
5807*e038c9c4Sjoerg     return;
5808*e038c9c4Sjoerg   }
5809*e038c9c4Sjoerg 
5810*e038c9c4Sjoerg   const ParmVarDecl *HandlerParam = getFunctionOrMethodParam(
5811*e038c9c4Sjoerg       D, AsyncAttr->getCompletionHandlerIndex().getASTIndex());
5812*e038c9c4Sjoerg   // handleSwiftAsyncAttr already verified the type is correct, so no need to
5813*e038c9c4Sjoerg   // double-check it here.
5814*e038c9c4Sjoerg   const auto *FuncTy = HandlerParam->getType()
5815*e038c9c4Sjoerg                            ->castAs<BlockPointerType>()
5816*e038c9c4Sjoerg                            ->getPointeeType()
5817*e038c9c4Sjoerg                            ->getAs<FunctionProtoType>();
5818*e038c9c4Sjoerg   ArrayRef<QualType> BlockParams;
5819*e038c9c4Sjoerg   if (FuncTy)
5820*e038c9c4Sjoerg     BlockParams = FuncTy->getParamTypes();
5821*e038c9c4Sjoerg 
5822*e038c9c4Sjoerg   switch (ErrorAttr->getConvention()) {
5823*e038c9c4Sjoerg   case SwiftAsyncErrorAttr::ZeroArgument:
5824*e038c9c4Sjoerg   case SwiftAsyncErrorAttr::NonZeroArgument: {
5825*e038c9c4Sjoerg     uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();
5826*e038c9c4Sjoerg     if (ParamIdx == 0 || ParamIdx > BlockParams.size()) {
5827*e038c9c4Sjoerg       S.Diag(ErrorAttr->getLocation(),
5828*e038c9c4Sjoerg              diag::err_attribute_argument_out_of_bounds) << ErrorAttr << 2;
5829*e038c9c4Sjoerg       return;
5830*e038c9c4Sjoerg     }
5831*e038c9c4Sjoerg     QualType ErrorParam = BlockParams[ParamIdx - 1];
5832*e038c9c4Sjoerg     if (!ErrorParam->isIntegralType(S.Context)) {
5833*e038c9c4Sjoerg       StringRef ConvStr =
5834*e038c9c4Sjoerg           ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
5835*e038c9c4Sjoerg               ? "zero_argument"
5836*e038c9c4Sjoerg               : "nonzero_argument";
5837*e038c9c4Sjoerg       S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral)
5838*e038c9c4Sjoerg           << ErrorAttr << ConvStr << ParamIdx << ErrorParam;
5839*e038c9c4Sjoerg       return;
5840*e038c9c4Sjoerg     }
5841*e038c9c4Sjoerg     break;
5842*e038c9c4Sjoerg   }
5843*e038c9c4Sjoerg   case SwiftAsyncErrorAttr::NonNullError: {
5844*e038c9c4Sjoerg     bool AnyErrorParams = false;
5845*e038c9c4Sjoerg     for (QualType Param : BlockParams) {
5846*e038c9c4Sjoerg       // Check for NSError *.
5847*e038c9c4Sjoerg       if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) {
5848*e038c9c4Sjoerg         if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {
5849*e038c9c4Sjoerg           if (ID->getIdentifier() == S.getNSErrorIdent()) {
5850*e038c9c4Sjoerg             AnyErrorParams = true;
5851*e038c9c4Sjoerg             break;
5852*e038c9c4Sjoerg           }
5853*e038c9c4Sjoerg         }
5854*e038c9c4Sjoerg       }
5855*e038c9c4Sjoerg       // Check for CFError *.
5856*e038c9c4Sjoerg       if (const auto *PtrTy = Param->getAs<PointerType>()) {
5857*e038c9c4Sjoerg         if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {
5858*e038c9c4Sjoerg           if (S.isCFError(RT->getDecl())) {
5859*e038c9c4Sjoerg             AnyErrorParams = true;
5860*e038c9c4Sjoerg             break;
5861*e038c9c4Sjoerg           }
5862*e038c9c4Sjoerg         }
5863*e038c9c4Sjoerg       }
5864*e038c9c4Sjoerg     }
5865*e038c9c4Sjoerg 
5866*e038c9c4Sjoerg     if (!AnyErrorParams) {
5867*e038c9c4Sjoerg       S.Diag(ErrorAttr->getLocation(),
5868*e038c9c4Sjoerg              diag::err_swift_async_error_no_error_parameter)
5869*e038c9c4Sjoerg           << ErrorAttr << isa<ObjCMethodDecl>(D);
5870*e038c9c4Sjoerg       return;
5871*e038c9c4Sjoerg     }
5872*e038c9c4Sjoerg     break;
5873*e038c9c4Sjoerg   }
5874*e038c9c4Sjoerg   case SwiftAsyncErrorAttr::None:
5875*e038c9c4Sjoerg     break;
5876*e038c9c4Sjoerg   }
5877*e038c9c4Sjoerg }
5878*e038c9c4Sjoerg 
handleSwiftAsyncError(Sema & S,Decl * D,const ParsedAttr & AL)5879*e038c9c4Sjoerg static void handleSwiftAsyncError(Sema &S, Decl *D, const ParsedAttr &AL) {
5880*e038c9c4Sjoerg   IdentifierLoc *IDLoc = AL.getArgAsIdent(0);
5881*e038c9c4Sjoerg   SwiftAsyncErrorAttr::ConventionKind ConvKind;
5882*e038c9c4Sjoerg   if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(),
5883*e038c9c4Sjoerg                                                        ConvKind)) {
5884*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
5885*e038c9c4Sjoerg         << AL << IDLoc->Ident;
5886*e038c9c4Sjoerg     return;
5887*e038c9c4Sjoerg   }
5888*e038c9c4Sjoerg 
5889*e038c9c4Sjoerg   uint32_t ParamIdx = 0;
5890*e038c9c4Sjoerg   switch (ConvKind) {
5891*e038c9c4Sjoerg   case SwiftAsyncErrorAttr::ZeroArgument:
5892*e038c9c4Sjoerg   case SwiftAsyncErrorAttr::NonZeroArgument: {
5893*e038c9c4Sjoerg     if (!AL.checkExactlyNumArgs(S, 2))
5894*e038c9c4Sjoerg       return;
5895*e038c9c4Sjoerg 
5896*e038c9c4Sjoerg     Expr *IdxExpr = AL.getArgAsExpr(1);
5897*e038c9c4Sjoerg     if (!checkUInt32Argument(S, AL, IdxExpr, ParamIdx))
5898*e038c9c4Sjoerg       return;
5899*e038c9c4Sjoerg     break;
5900*e038c9c4Sjoerg   }
5901*e038c9c4Sjoerg   case SwiftAsyncErrorAttr::NonNullError:
5902*e038c9c4Sjoerg   case SwiftAsyncErrorAttr::None: {
5903*e038c9c4Sjoerg     if (!AL.checkExactlyNumArgs(S, 1))
5904*e038c9c4Sjoerg       return;
5905*e038c9c4Sjoerg     break;
5906*e038c9c4Sjoerg   }
5907*e038c9c4Sjoerg   }
5908*e038c9c4Sjoerg 
5909*e038c9c4Sjoerg   auto *ErrorAttr =
5910*e038c9c4Sjoerg       ::new (S.Context) SwiftAsyncErrorAttr(S.Context, AL, ConvKind, ParamIdx);
5911*e038c9c4Sjoerg   D->addAttr(ErrorAttr);
5912*e038c9c4Sjoerg 
5913*e038c9c4Sjoerg   if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>())
5914*e038c9c4Sjoerg     checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
5915*e038c9c4Sjoerg }
5916*e038c9c4Sjoerg 
5917*e038c9c4Sjoerg // For a function, this will validate a compound Swift name, e.g.
5918*e038c9c4Sjoerg // <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
5919*e038c9c4Sjoerg // the function will output the number of parameter names, and whether this is a
5920*e038c9c4Sjoerg // single-arg initializer.
5921*e038c9c4Sjoerg //
5922*e038c9c4Sjoerg // For a type, enum constant, property, or variable declaration, this will
5923*e038c9c4Sjoerg // validate either a simple identifier, or a qualified
5924*e038c9c4Sjoerg // <code>context.identifier</code> name.
5925*e038c9c4Sjoerg static bool
validateSwiftFunctionName(Sema & S,const ParsedAttr & AL,SourceLocation Loc,StringRef Name,unsigned & SwiftParamCount,bool & IsSingleParamInit)5926*e038c9c4Sjoerg validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc,
5927*e038c9c4Sjoerg                           StringRef Name, unsigned &SwiftParamCount,
5928*e038c9c4Sjoerg                           bool &IsSingleParamInit) {
5929*e038c9c4Sjoerg   SwiftParamCount = 0;
5930*e038c9c4Sjoerg   IsSingleParamInit = false;
5931*e038c9c4Sjoerg 
5932*e038c9c4Sjoerg   // Check whether this will be mapped to a getter or setter of a property.
5933*e038c9c4Sjoerg   bool IsGetter = false, IsSetter = false;
5934*e038c9c4Sjoerg   if (Name.startswith("getter:")) {
5935*e038c9c4Sjoerg     IsGetter = true;
5936*e038c9c4Sjoerg     Name = Name.substr(7);
5937*e038c9c4Sjoerg   } else if (Name.startswith("setter:")) {
5938*e038c9c4Sjoerg     IsSetter = true;
5939*e038c9c4Sjoerg     Name = Name.substr(7);
5940*e038c9c4Sjoerg   }
5941*e038c9c4Sjoerg 
5942*e038c9c4Sjoerg   if (Name.back() != ')') {
5943*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
5944*e038c9c4Sjoerg     return false;
5945*e038c9c4Sjoerg   }
5946*e038c9c4Sjoerg 
5947*e038c9c4Sjoerg   bool IsMember = false;
5948*e038c9c4Sjoerg   StringRef ContextName, BaseName, Parameters;
5949*e038c9c4Sjoerg 
5950*e038c9c4Sjoerg   std::tie(BaseName, Parameters) = Name.split('(');
5951*e038c9c4Sjoerg 
5952*e038c9c4Sjoerg   // Split at the first '.', if it exists, which separates the context name
5953*e038c9c4Sjoerg   // from the base name.
5954*e038c9c4Sjoerg   std::tie(ContextName, BaseName) = BaseName.split('.');
5955*e038c9c4Sjoerg   if (BaseName.empty()) {
5956*e038c9c4Sjoerg     BaseName = ContextName;
5957*e038c9c4Sjoerg     ContextName = StringRef();
5958*e038c9c4Sjoerg   } else if (ContextName.empty() || !isValidIdentifier(ContextName)) {
5959*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
5960*e038c9c4Sjoerg         << AL << /*context*/ 1;
5961*e038c9c4Sjoerg     return false;
5962*e038c9c4Sjoerg   } else {
5963*e038c9c4Sjoerg     IsMember = true;
5964*e038c9c4Sjoerg   }
5965*e038c9c4Sjoerg 
5966*e038c9c4Sjoerg   if (!isValidIdentifier(BaseName) || BaseName == "_") {
5967*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
5968*e038c9c4Sjoerg         << AL << /*basename*/ 0;
5969*e038c9c4Sjoerg     return false;
5970*e038c9c4Sjoerg   }
5971*e038c9c4Sjoerg 
5972*e038c9c4Sjoerg   bool IsSubscript = BaseName == "subscript";
5973*e038c9c4Sjoerg   // A subscript accessor must be a getter or setter.
5974*e038c9c4Sjoerg   if (IsSubscript && !IsGetter && !IsSetter) {
5975*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
5976*e038c9c4Sjoerg         << AL << /* getter or setter */ 0;
5977*e038c9c4Sjoerg     return false;
5978*e038c9c4Sjoerg   }
5979*e038c9c4Sjoerg 
5980*e038c9c4Sjoerg   if (Parameters.empty()) {
5981*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;
5982*e038c9c4Sjoerg     return false;
5983*e038c9c4Sjoerg   }
5984*e038c9c4Sjoerg 
5985*e038c9c4Sjoerg   assert(Parameters.back() == ')' && "expected ')'");
5986*e038c9c4Sjoerg   Parameters = Parameters.drop_back(); // ')'
5987*e038c9c4Sjoerg 
5988*e038c9c4Sjoerg   if (Parameters.empty()) {
5989*e038c9c4Sjoerg     // Setters and subscripts must have at least one parameter.
5990*e038c9c4Sjoerg     if (IsSubscript) {
5991*e038c9c4Sjoerg       S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
5992*e038c9c4Sjoerg           << AL << /* have at least one parameter */1;
5993*e038c9c4Sjoerg       return false;
5994*e038c9c4Sjoerg     }
5995*e038c9c4Sjoerg 
5996*e038c9c4Sjoerg     if (IsSetter) {
5997*e038c9c4Sjoerg       S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;
5998*e038c9c4Sjoerg       return false;
5999*e038c9c4Sjoerg     }
6000*e038c9c4Sjoerg 
6001*e038c9c4Sjoerg     return true;
6002*e038c9c4Sjoerg   }
6003*e038c9c4Sjoerg 
6004*e038c9c4Sjoerg   if (Parameters.back() != ':') {
6005*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
6006*e038c9c4Sjoerg     return false;
6007*e038c9c4Sjoerg   }
6008*e038c9c4Sjoerg 
6009*e038c9c4Sjoerg   StringRef CurrentParam;
6010*e038c9c4Sjoerg   llvm::Optional<unsigned> SelfLocation;
6011*e038c9c4Sjoerg   unsigned NewValueCount = 0;
6012*e038c9c4Sjoerg   llvm::Optional<unsigned> NewValueLocation;
6013*e038c9c4Sjoerg   do {
6014*e038c9c4Sjoerg     std::tie(CurrentParam, Parameters) = Parameters.split(':');
6015*e038c9c4Sjoerg 
6016*e038c9c4Sjoerg     if (!isValidIdentifier(CurrentParam)) {
6017*e038c9c4Sjoerg       S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
6018*e038c9c4Sjoerg           << AL << /*parameter*/2;
6019*e038c9c4Sjoerg       return false;
6020*e038c9c4Sjoerg     }
6021*e038c9c4Sjoerg 
6022*e038c9c4Sjoerg     if (IsMember && CurrentParam == "self") {
6023*e038c9c4Sjoerg       // "self" indicates the "self" argument for a member.
6024*e038c9c4Sjoerg 
6025*e038c9c4Sjoerg       // More than one "self"?
6026*e038c9c4Sjoerg       if (SelfLocation) {
6027*e038c9c4Sjoerg         S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;
6028*e038c9c4Sjoerg         return false;
6029*e038c9c4Sjoerg       }
6030*e038c9c4Sjoerg 
6031*e038c9c4Sjoerg       // The "self" location is the current parameter.
6032*e038c9c4Sjoerg       SelfLocation = SwiftParamCount;
6033*e038c9c4Sjoerg     } else if (CurrentParam == "newValue") {
6034*e038c9c4Sjoerg       // "newValue" indicates the "newValue" argument for a setter.
6035*e038c9c4Sjoerg 
6036*e038c9c4Sjoerg       // There should only be one 'newValue', but it's only significant for
6037*e038c9c4Sjoerg       // subscript accessors, so don't error right away.
6038*e038c9c4Sjoerg       ++NewValueCount;
6039*e038c9c4Sjoerg 
6040*e038c9c4Sjoerg       NewValueLocation = SwiftParamCount;
6041*e038c9c4Sjoerg     }
6042*e038c9c4Sjoerg 
6043*e038c9c4Sjoerg     ++SwiftParamCount;
6044*e038c9c4Sjoerg   } while (!Parameters.empty());
6045*e038c9c4Sjoerg 
6046*e038c9c4Sjoerg   // Only instance subscripts are currently supported.
6047*e038c9c4Sjoerg   if (IsSubscript && !SelfLocation) {
6048*e038c9c4Sjoerg     S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
6049*e038c9c4Sjoerg         << AL << /*have a 'self:' parameter*/2;
6050*e038c9c4Sjoerg     return false;
6051*e038c9c4Sjoerg   }
6052*e038c9c4Sjoerg 
6053*e038c9c4Sjoerg   IsSingleParamInit =
6054*e038c9c4Sjoerg         SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
6055*e038c9c4Sjoerg 
6056*e038c9c4Sjoerg   // Check the number of parameters for a getter/setter.
6057*e038c9c4Sjoerg   if (IsGetter || IsSetter) {
6058*e038c9c4Sjoerg     // Setters have one parameter for the new value.
6059*e038c9c4Sjoerg     unsigned NumExpectedParams = IsGetter ? 0 : 1;
6060*e038c9c4Sjoerg     unsigned ParamDiag =
6061*e038c9c4Sjoerg         IsGetter ? diag::warn_attr_swift_name_getter_parameters
6062*e038c9c4Sjoerg                  : diag::warn_attr_swift_name_setter_parameters;
6063*e038c9c4Sjoerg 
6064*e038c9c4Sjoerg     // Instance methods have one parameter for "self".
6065*e038c9c4Sjoerg     if (SelfLocation)
6066*e038c9c4Sjoerg       ++NumExpectedParams;
6067*e038c9c4Sjoerg 
6068*e038c9c4Sjoerg     // Subscripts may have additional parameters beyond the expected params for
6069*e038c9c4Sjoerg     // the index.
6070*e038c9c4Sjoerg     if (IsSubscript) {
6071*e038c9c4Sjoerg       if (SwiftParamCount < NumExpectedParams) {
6072*e038c9c4Sjoerg         S.Diag(Loc, ParamDiag) << AL;
6073*e038c9c4Sjoerg         return false;
6074*e038c9c4Sjoerg       }
6075*e038c9c4Sjoerg 
6076*e038c9c4Sjoerg       // A subscript setter must explicitly label its newValue parameter to
6077*e038c9c4Sjoerg       // distinguish it from index parameters.
6078*e038c9c4Sjoerg       if (IsSetter) {
6079*e038c9c4Sjoerg         if (!NewValueLocation) {
6080*e038c9c4Sjoerg           S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)
6081*e038c9c4Sjoerg               << AL;
6082*e038c9c4Sjoerg           return false;
6083*e038c9c4Sjoerg         }
6084*e038c9c4Sjoerg         if (NewValueCount > 1) {
6085*e038c9c4Sjoerg           S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
6086*e038c9c4Sjoerg               << AL;
6087*e038c9c4Sjoerg           return false;
6088*e038c9c4Sjoerg         }
6089*e038c9c4Sjoerg       } else {
6090*e038c9c4Sjoerg         // Subscript getters should have no 'newValue:' parameter.
6091*e038c9c4Sjoerg         if (NewValueLocation) {
6092*e038c9c4Sjoerg           S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)
6093*e038c9c4Sjoerg               << AL;
6094*e038c9c4Sjoerg           return false;
6095*e038c9c4Sjoerg         }
6096*e038c9c4Sjoerg       }
6097*e038c9c4Sjoerg     } else {
6098*e038c9c4Sjoerg       // Property accessors must have exactly the number of expected params.
6099*e038c9c4Sjoerg       if (SwiftParamCount != NumExpectedParams) {
6100*e038c9c4Sjoerg         S.Diag(Loc, ParamDiag) << AL;
6101*e038c9c4Sjoerg         return false;
6102*e038c9c4Sjoerg       }
6103*e038c9c4Sjoerg     }
6104*e038c9c4Sjoerg   }
6105*e038c9c4Sjoerg 
6106*e038c9c4Sjoerg   return true;
6107*e038c9c4Sjoerg }
6108*e038c9c4Sjoerg 
DiagnoseSwiftName(Decl * D,StringRef Name,SourceLocation Loc,const ParsedAttr & AL,bool IsAsync)6109*e038c9c4Sjoerg bool Sema::DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
6110*e038c9c4Sjoerg                              const ParsedAttr &AL, bool IsAsync) {
6111*e038c9c4Sjoerg   if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
6112*e038c9c4Sjoerg     ArrayRef<ParmVarDecl*> Params;
6113*e038c9c4Sjoerg     unsigned ParamCount;
6114*e038c9c4Sjoerg 
6115*e038c9c4Sjoerg     if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) {
6116*e038c9c4Sjoerg       ParamCount = Method->getSelector().getNumArgs();
6117*e038c9c4Sjoerg       Params = Method->parameters().slice(0, ParamCount);
6118*e038c9c4Sjoerg     } else {
6119*e038c9c4Sjoerg       const auto *F = cast<FunctionDecl>(D);
6120*e038c9c4Sjoerg 
6121*e038c9c4Sjoerg       ParamCount = F->getNumParams();
6122*e038c9c4Sjoerg       Params = F->parameters();
6123*e038c9c4Sjoerg 
6124*e038c9c4Sjoerg       if (!F->hasWrittenPrototype()) {
6125*e038c9c4Sjoerg         Diag(Loc, diag::warn_attribute_wrong_decl_type) << AL
6126*e038c9c4Sjoerg             << ExpectedFunctionWithProtoType;
6127*e038c9c4Sjoerg         return false;
6128*e038c9c4Sjoerg       }
6129*e038c9c4Sjoerg     }
6130*e038c9c4Sjoerg 
6131*e038c9c4Sjoerg     // The async name drops the last callback parameter.
6132*e038c9c4Sjoerg     if (IsAsync) {
6133*e038c9c4Sjoerg       if (ParamCount == 0) {
6134*e038c9c4Sjoerg         Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)
6135*e038c9c4Sjoerg             << AL << isa<ObjCMethodDecl>(D);
6136*e038c9c4Sjoerg         return false;
6137*e038c9c4Sjoerg       }
6138*e038c9c4Sjoerg       ParamCount -= 1;
6139*e038c9c4Sjoerg     }
6140*e038c9c4Sjoerg 
6141*e038c9c4Sjoerg     unsigned SwiftParamCount;
6142*e038c9c4Sjoerg     bool IsSingleParamInit;
6143*e038c9c4Sjoerg     if (!validateSwiftFunctionName(*this, AL, Loc, Name,
6144*e038c9c4Sjoerg                                    SwiftParamCount, IsSingleParamInit))
6145*e038c9c4Sjoerg       return false;
6146*e038c9c4Sjoerg 
6147*e038c9c4Sjoerg     bool ParamCountValid;
6148*e038c9c4Sjoerg     if (SwiftParamCount == ParamCount) {
6149*e038c9c4Sjoerg       ParamCountValid = true;
6150*e038c9c4Sjoerg     } else if (SwiftParamCount > ParamCount) {
6151*e038c9c4Sjoerg       ParamCountValid = IsSingleParamInit && ParamCount == 0;
6152*e038c9c4Sjoerg     } else {
6153*e038c9c4Sjoerg       // We have fewer Swift parameters than Objective-C parameters, but that
6154*e038c9c4Sjoerg       // might be because we've transformed some of them. Check for potential
6155*e038c9c4Sjoerg       // "out" parameters and err on the side of not warning.
6156*e038c9c4Sjoerg       unsigned MaybeOutParamCount =
6157*e038c9c4Sjoerg           std::count_if(Params.begin(), Params.end(),
6158*e038c9c4Sjoerg                         [](const ParmVarDecl *Param) -> bool {
6159*e038c9c4Sjoerg         QualType ParamTy = Param->getType();
6160*e038c9c4Sjoerg         if (ParamTy->isReferenceType() || ParamTy->isPointerType())
6161*e038c9c4Sjoerg           return !ParamTy->getPointeeType().isConstQualified();
6162*e038c9c4Sjoerg         return false;
6163*e038c9c4Sjoerg       });
6164*e038c9c4Sjoerg 
6165*e038c9c4Sjoerg       ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
6166*e038c9c4Sjoerg     }
6167*e038c9c4Sjoerg 
6168*e038c9c4Sjoerg     if (!ParamCountValid) {
6169*e038c9c4Sjoerg       Diag(Loc, diag::warn_attr_swift_name_num_params)
6170*e038c9c4Sjoerg           << (SwiftParamCount > ParamCount) << AL << ParamCount
6171*e038c9c4Sjoerg           << SwiftParamCount;
6172*e038c9c4Sjoerg       return false;
6173*e038c9c4Sjoerg     }
6174*e038c9c4Sjoerg   } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) ||
6175*e038c9c4Sjoerg               isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) ||
6176*e038c9c4Sjoerg               isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) ||
6177*e038c9c4Sjoerg               isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) &&
6178*e038c9c4Sjoerg              !IsAsync) {
6179*e038c9c4Sjoerg     StringRef ContextName, BaseName;
6180*e038c9c4Sjoerg 
6181*e038c9c4Sjoerg     std::tie(ContextName, BaseName) = Name.split('.');
6182*e038c9c4Sjoerg     if (BaseName.empty()) {
6183*e038c9c4Sjoerg       BaseName = ContextName;
6184*e038c9c4Sjoerg       ContextName = StringRef();
6185*e038c9c4Sjoerg     } else if (!isValidIdentifier(ContextName)) {
6186*e038c9c4Sjoerg       Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL
6187*e038c9c4Sjoerg           << /*context*/1;
6188*e038c9c4Sjoerg       return false;
6189*e038c9c4Sjoerg     }
6190*e038c9c4Sjoerg 
6191*e038c9c4Sjoerg     if (!isValidIdentifier(BaseName)) {
6192*e038c9c4Sjoerg       Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL
6193*e038c9c4Sjoerg           << /*basename*/0;
6194*e038c9c4Sjoerg       return false;
6195*e038c9c4Sjoerg     }
6196*e038c9c4Sjoerg   } else {
6197*e038c9c4Sjoerg     Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;
6198*e038c9c4Sjoerg     return false;
6199*e038c9c4Sjoerg   }
6200*e038c9c4Sjoerg   return true;
6201*e038c9c4Sjoerg }
6202*e038c9c4Sjoerg 
handleSwiftName(Sema & S,Decl * D,const ParsedAttr & AL)6203*e038c9c4Sjoerg static void handleSwiftName(Sema &S, Decl *D, const ParsedAttr &AL) {
6204*e038c9c4Sjoerg   StringRef Name;
6205*e038c9c4Sjoerg   SourceLocation Loc;
6206*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
6207*e038c9c4Sjoerg     return;
6208*e038c9c4Sjoerg 
6209*e038c9c4Sjoerg   if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/false))
6210*e038c9c4Sjoerg     return;
6211*e038c9c4Sjoerg 
6212*e038c9c4Sjoerg   D->addAttr(::new (S.Context) SwiftNameAttr(S.Context, AL, Name));
6213*e038c9c4Sjoerg }
6214*e038c9c4Sjoerg 
handleSwiftAsyncName(Sema & S,Decl * D,const ParsedAttr & AL)6215*e038c9c4Sjoerg static void handleSwiftAsyncName(Sema &S, Decl *D, const ParsedAttr &AL) {
6216*e038c9c4Sjoerg   StringRef Name;
6217*e038c9c4Sjoerg   SourceLocation Loc;
6218*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
6219*e038c9c4Sjoerg     return;
6220*e038c9c4Sjoerg 
6221*e038c9c4Sjoerg   if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/true))
6222*e038c9c4Sjoerg     return;
6223*e038c9c4Sjoerg 
6224*e038c9c4Sjoerg   D->addAttr(::new (S.Context) SwiftAsyncNameAttr(S.Context, AL, Name));
6225*e038c9c4Sjoerg }
6226*e038c9c4Sjoerg 
handleSwiftNewType(Sema & S,Decl * D,const ParsedAttr & AL)6227*e038c9c4Sjoerg static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) {
6228*e038c9c4Sjoerg   // Make sure that there is an identifier as the annotation's single argument.
6229*e038c9c4Sjoerg   if (!AL.checkExactlyNumArgs(S, 1))
6230*e038c9c4Sjoerg     return;
6231*e038c9c4Sjoerg 
6232*e038c9c4Sjoerg   if (!AL.isArgIdent(0)) {
6233*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
6234*e038c9c4Sjoerg         << AL << AANT_ArgumentIdentifier;
6235*e038c9c4Sjoerg     return;
6236*e038c9c4Sjoerg   }
6237*e038c9c4Sjoerg 
6238*e038c9c4Sjoerg   SwiftNewTypeAttr::NewtypeKind Kind;
6239*e038c9c4Sjoerg   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
6240*e038c9c4Sjoerg   if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
6241*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
6242*e038c9c4Sjoerg     return;
6243*e038c9c4Sjoerg   }
6244*e038c9c4Sjoerg 
6245*e038c9c4Sjoerg   if (!isa<TypedefNameDecl>(D)) {
6246*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
6247*e038c9c4Sjoerg         << AL << "typedefs";
6248*e038c9c4Sjoerg     return;
6249*e038c9c4Sjoerg   }
6250*e038c9c4Sjoerg 
6251*e038c9c4Sjoerg   D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind));
6252*e038c9c4Sjoerg }
6253*e038c9c4Sjoerg 
handleSwiftAsyncAttr(Sema & S,Decl * D,const ParsedAttr & AL)6254*e038c9c4Sjoerg static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6255*e038c9c4Sjoerg   if (!AL.isArgIdent(0)) {
6256*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
6257*e038c9c4Sjoerg         << AL << 1 << AANT_ArgumentIdentifier;
6258*e038c9c4Sjoerg     return;
6259*e038c9c4Sjoerg   }
6260*e038c9c4Sjoerg 
6261*e038c9c4Sjoerg   SwiftAsyncAttr::Kind Kind;
6262*e038c9c4Sjoerg   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
6263*e038c9c4Sjoerg   if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
6264*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
6265*e038c9c4Sjoerg     return;
6266*e038c9c4Sjoerg   }
6267*e038c9c4Sjoerg 
6268*e038c9c4Sjoerg   ParamIdx Idx;
6269*e038c9c4Sjoerg   if (Kind == SwiftAsyncAttr::None) {
6270*e038c9c4Sjoerg     // If this is 'none', then there shouldn't be any additional arguments.
6271*e038c9c4Sjoerg     if (!AL.checkExactlyNumArgs(S, 1))
6272*e038c9c4Sjoerg       return;
6273*e038c9c4Sjoerg   } else {
6274*e038c9c4Sjoerg     // Non-none swift_async requires a completion handler index argument.
6275*e038c9c4Sjoerg     if (!AL.checkExactlyNumArgs(S, 2))
6276*e038c9c4Sjoerg       return;
6277*e038c9c4Sjoerg 
6278*e038c9c4Sjoerg     Expr *HandlerIdx = AL.getArgAsExpr(1);
6279*e038c9c4Sjoerg     if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, HandlerIdx, Idx))
6280*e038c9c4Sjoerg       return;
6281*e038c9c4Sjoerg 
6282*e038c9c4Sjoerg     const ParmVarDecl *CompletionBlock =
6283*e038c9c4Sjoerg         getFunctionOrMethodParam(D, Idx.getASTIndex());
6284*e038c9c4Sjoerg     QualType CompletionBlockType = CompletionBlock->getType();
6285*e038c9c4Sjoerg     if (!CompletionBlockType->isBlockPointerType()) {
6286*e038c9c4Sjoerg       S.Diag(CompletionBlock->getLocation(),
6287*e038c9c4Sjoerg              diag::err_swift_async_bad_block_type)
6288*e038c9c4Sjoerg           << CompletionBlock->getType();
6289*e038c9c4Sjoerg       return;
6290*e038c9c4Sjoerg     }
6291*e038c9c4Sjoerg     QualType BlockTy =
6292*e038c9c4Sjoerg         CompletionBlockType->castAs<BlockPointerType>()->getPointeeType();
6293*e038c9c4Sjoerg     if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) {
6294*e038c9c4Sjoerg       S.Diag(CompletionBlock->getLocation(),
6295*e038c9c4Sjoerg              diag::err_swift_async_bad_block_type)
6296*e038c9c4Sjoerg           << CompletionBlock->getType();
6297*e038c9c4Sjoerg       return;
6298*e038c9c4Sjoerg     }
6299*e038c9c4Sjoerg   }
6300*e038c9c4Sjoerg 
6301*e038c9c4Sjoerg   auto *AsyncAttr =
6302*e038c9c4Sjoerg       ::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx);
6303*e038c9c4Sjoerg   D->addAttr(AsyncAttr);
6304*e038c9c4Sjoerg 
6305*e038c9c4Sjoerg   if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>())
6306*e038c9c4Sjoerg     checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
6307*e038c9c4Sjoerg }
6308*e038c9c4Sjoerg 
63097330f729Sjoerg //===----------------------------------------------------------------------===//
63107330f729Sjoerg // Microsoft specific attribute handlers.
63117330f729Sjoerg //===----------------------------------------------------------------------===//
63127330f729Sjoerg 
mergeUuidAttr(Decl * D,const AttributeCommonInfo & CI,StringRef UuidAsWritten,MSGuidDecl * GuidDecl)63137330f729Sjoerg UuidAttr *Sema::mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
6314*e038c9c4Sjoerg                               StringRef UuidAsWritten, MSGuidDecl *GuidDecl) {
63157330f729Sjoerg   if (const auto *UA = D->getAttr<UuidAttr>()) {
6316*e038c9c4Sjoerg     if (declaresSameEntity(UA->getGuidDecl(), GuidDecl))
63177330f729Sjoerg       return nullptr;
6318*e038c9c4Sjoerg     if (!UA->getGuid().empty()) {
63197330f729Sjoerg       Diag(UA->getLocation(), diag::err_mismatched_uuid);
63207330f729Sjoerg       Diag(CI.getLoc(), diag::note_previous_uuid);
63217330f729Sjoerg       D->dropAttr<UuidAttr>();
63227330f729Sjoerg     }
6323*e038c9c4Sjoerg   }
63247330f729Sjoerg 
6325*e038c9c4Sjoerg   return ::new (Context) UuidAttr(Context, CI, UuidAsWritten, GuidDecl);
63267330f729Sjoerg }
63277330f729Sjoerg 
handleUuidAttr(Sema & S,Decl * D,const ParsedAttr & AL)63287330f729Sjoerg static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
63297330f729Sjoerg   if (!S.LangOpts.CPlusPlus) {
63307330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
63317330f729Sjoerg         << AL << AttributeLangSupport::C;
63327330f729Sjoerg     return;
63337330f729Sjoerg   }
63347330f729Sjoerg 
6335*e038c9c4Sjoerg   StringRef OrigStrRef;
63367330f729Sjoerg   SourceLocation LiteralLoc;
6337*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, OrigStrRef, &LiteralLoc))
63387330f729Sjoerg     return;
63397330f729Sjoerg 
63407330f729Sjoerg   // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
63417330f729Sjoerg   // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former.
6342*e038c9c4Sjoerg   StringRef StrRef = OrigStrRef;
63437330f729Sjoerg   if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}')
63447330f729Sjoerg     StrRef = StrRef.drop_front().drop_back();
63457330f729Sjoerg 
63467330f729Sjoerg   // Validate GUID length.
63477330f729Sjoerg   if (StrRef.size() != 36) {
63487330f729Sjoerg     S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
63497330f729Sjoerg     return;
63507330f729Sjoerg   }
63517330f729Sjoerg 
63527330f729Sjoerg   for (unsigned i = 0; i < 36; ++i) {
63537330f729Sjoerg     if (i == 8 || i == 13 || i == 18 || i == 23) {
63547330f729Sjoerg       if (StrRef[i] != '-') {
63557330f729Sjoerg         S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
63567330f729Sjoerg         return;
63577330f729Sjoerg       }
63587330f729Sjoerg     } else if (!isHexDigit(StrRef[i])) {
63597330f729Sjoerg       S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
63607330f729Sjoerg       return;
63617330f729Sjoerg     }
63627330f729Sjoerg   }
63637330f729Sjoerg 
6364*e038c9c4Sjoerg   // Convert to our parsed format and canonicalize.
6365*e038c9c4Sjoerg   MSGuidDecl::Parts Parsed;
6366*e038c9c4Sjoerg   StrRef.substr(0, 8).getAsInteger(16, Parsed.Part1);
6367*e038c9c4Sjoerg   StrRef.substr(9, 4).getAsInteger(16, Parsed.Part2);
6368*e038c9c4Sjoerg   StrRef.substr(14, 4).getAsInteger(16, Parsed.Part3);
6369*e038c9c4Sjoerg   for (unsigned i = 0; i != 8; ++i)
6370*e038c9c4Sjoerg     StrRef.substr(19 + 2 * i + (i >= 2 ? 1 : 0), 2)
6371*e038c9c4Sjoerg         .getAsInteger(16, Parsed.Part4And5[i]);
6372*e038c9c4Sjoerg   MSGuidDecl *Guid = S.Context.getMSGuidDecl(Parsed);
6373*e038c9c4Sjoerg 
63747330f729Sjoerg   // FIXME: It'd be nice to also emit a fixit removing uuid(...) (and, if it's
63757330f729Sjoerg   // the only thing in the [] list, the [] too), and add an insertion of
63767330f729Sjoerg   // __declspec(uuid(...)).  But sadly, neither the SourceLocs of the commas
63777330f729Sjoerg   // separating attributes nor of the [ and the ] are in the AST.
63787330f729Sjoerg   // Cf "SourceLocations of attribute list delimiters - [[ ... , ... ]] etc"
63797330f729Sjoerg   // on cfe-dev.
63807330f729Sjoerg   if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling.
63817330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated);
63827330f729Sjoerg 
6383*e038c9c4Sjoerg   UuidAttr *UA = S.mergeUuidAttr(D, AL, OrigStrRef, Guid);
63847330f729Sjoerg   if (UA)
63857330f729Sjoerg     D->addAttr(UA);
63867330f729Sjoerg }
63877330f729Sjoerg 
handleMSInheritanceAttr(Sema & S,Decl * D,const ParsedAttr & AL)63887330f729Sjoerg static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
63897330f729Sjoerg   if (!S.LangOpts.CPlusPlus) {
63907330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
63917330f729Sjoerg         << AL << AttributeLangSupport::C;
63927330f729Sjoerg     return;
63937330f729Sjoerg   }
63947330f729Sjoerg   MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
6395*e038c9c4Sjoerg       D, AL, /*BestCase=*/true, (MSInheritanceModel)AL.getSemanticSpelling());
63967330f729Sjoerg   if (IA) {
63977330f729Sjoerg     D->addAttr(IA);
63987330f729Sjoerg     S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D));
63997330f729Sjoerg   }
64007330f729Sjoerg }
64017330f729Sjoerg 
handleDeclspecThreadAttr(Sema & S,Decl * D,const ParsedAttr & AL)64027330f729Sjoerg static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
64037330f729Sjoerg   const auto *VD = cast<VarDecl>(D);
64047330f729Sjoerg   if (!S.Context.getTargetInfo().isTLSSupported()) {
64057330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_thread_unsupported);
64067330f729Sjoerg     return;
64077330f729Sjoerg   }
64087330f729Sjoerg   if (VD->getTSCSpec() != TSCS_unspecified) {
64097330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_declspec_thread_on_thread_variable);
64107330f729Sjoerg     return;
64117330f729Sjoerg   }
64127330f729Sjoerg   if (VD->hasLocalStorage()) {
64137330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
64147330f729Sjoerg     return;
64157330f729Sjoerg   }
64167330f729Sjoerg   D->addAttr(::new (S.Context) ThreadAttr(S.Context, AL));
64177330f729Sjoerg }
64187330f729Sjoerg 
handleAbiTagAttr(Sema & S,Decl * D,const ParsedAttr & AL)64197330f729Sjoerg static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
64207330f729Sjoerg   SmallVector<StringRef, 4> Tags;
64217330f729Sjoerg   for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
64227330f729Sjoerg     StringRef Tag;
64237330f729Sjoerg     if (!S.checkStringLiteralArgumentAttr(AL, I, Tag))
64247330f729Sjoerg       return;
64257330f729Sjoerg     Tags.push_back(Tag);
64267330f729Sjoerg   }
64277330f729Sjoerg 
64287330f729Sjoerg   if (const auto *NS = dyn_cast<NamespaceDecl>(D)) {
64297330f729Sjoerg     if (!NS->isInline()) {
64307330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 0;
64317330f729Sjoerg       return;
64327330f729Sjoerg     }
64337330f729Sjoerg     if (NS->isAnonymousNamespace()) {
64347330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 1;
64357330f729Sjoerg       return;
64367330f729Sjoerg     }
64377330f729Sjoerg     if (AL.getNumArgs() == 0)
64387330f729Sjoerg       Tags.push_back(NS->getName());
6439*e038c9c4Sjoerg   } else if (!AL.checkAtLeastNumArgs(S, 1))
64407330f729Sjoerg     return;
64417330f729Sjoerg 
64427330f729Sjoerg   // Store tags sorted and without duplicates.
64437330f729Sjoerg   llvm::sort(Tags);
64447330f729Sjoerg   Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
64457330f729Sjoerg 
64467330f729Sjoerg   D->addAttr(::new (S.Context)
64477330f729Sjoerg                  AbiTagAttr(S.Context, AL, Tags.data(), Tags.size()));
64487330f729Sjoerg }
64497330f729Sjoerg 
handleARMInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)64507330f729Sjoerg static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
64517330f729Sjoerg   // Check the attribute arguments.
64527330f729Sjoerg   if (AL.getNumArgs() > 1) {
64537330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
64547330f729Sjoerg     return;
64557330f729Sjoerg   }
64567330f729Sjoerg 
64577330f729Sjoerg   StringRef Str;
64587330f729Sjoerg   SourceLocation ArgLoc;
64597330f729Sjoerg 
64607330f729Sjoerg   if (AL.getNumArgs() == 0)
64617330f729Sjoerg     Str = "";
64627330f729Sjoerg   else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
64637330f729Sjoerg     return;
64647330f729Sjoerg 
64657330f729Sjoerg   ARMInterruptAttr::InterruptType Kind;
64667330f729Sjoerg   if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
64677330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
64687330f729Sjoerg                                                                  << ArgLoc;
64697330f729Sjoerg     return;
64707330f729Sjoerg   }
64717330f729Sjoerg 
64727330f729Sjoerg   D->addAttr(::new (S.Context) ARMInterruptAttr(S.Context, AL, Kind));
64737330f729Sjoerg }
64747330f729Sjoerg 
handleMSP430InterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)64757330f729Sjoerg static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
64767330f729Sjoerg   // MSP430 'interrupt' attribute is applied to
64777330f729Sjoerg   // a function with no parameters and void return type.
64787330f729Sjoerg   if (!isFunctionOrMethod(D)) {
64797330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
64807330f729Sjoerg         << "'interrupt'" << ExpectedFunctionOrMethod;
64817330f729Sjoerg     return;
64827330f729Sjoerg   }
64837330f729Sjoerg 
64847330f729Sjoerg   if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
64857330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
64867330f729Sjoerg         << /*MSP430*/ 1 << 0;
64877330f729Sjoerg     return;
64887330f729Sjoerg   }
64897330f729Sjoerg 
64907330f729Sjoerg   if (!getFunctionOrMethodResultType(D)->isVoidType()) {
64917330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
64927330f729Sjoerg         << /*MSP430*/ 1 << 1;
64937330f729Sjoerg     return;
64947330f729Sjoerg   }
64957330f729Sjoerg 
64967330f729Sjoerg   // The attribute takes one integer argument.
6497*e038c9c4Sjoerg   if (!AL.checkExactlyNumArgs(S, 1))
64987330f729Sjoerg     return;
64997330f729Sjoerg 
65007330f729Sjoerg   if (!AL.isArgExpr(0)) {
65017330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
65027330f729Sjoerg         << AL << AANT_ArgumentIntegerConstant;
65037330f729Sjoerg     return;
65047330f729Sjoerg   }
65057330f729Sjoerg 
65067330f729Sjoerg   Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
6507*e038c9c4Sjoerg   Optional<llvm::APSInt> NumParams = llvm::APSInt(32);
6508*e038c9c4Sjoerg   if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(S.Context))) {
65097330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
65107330f729Sjoerg         << AL << AANT_ArgumentIntegerConstant
65117330f729Sjoerg         << NumParamsExpr->getSourceRange();
65127330f729Sjoerg     return;
65137330f729Sjoerg   }
65147330f729Sjoerg   // The argument should be in range 0..63.
6515*e038c9c4Sjoerg   unsigned Num = NumParams->getLimitedValue(255);
65167330f729Sjoerg   if (Num > 63) {
65177330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
6518*e038c9c4Sjoerg         << AL << (int)NumParams->getSExtValue()
65197330f729Sjoerg         << NumParamsExpr->getSourceRange();
65207330f729Sjoerg     return;
65217330f729Sjoerg   }
65227330f729Sjoerg 
65237330f729Sjoerg   D->addAttr(::new (S.Context) MSP430InterruptAttr(S.Context, AL, Num));
65247330f729Sjoerg   D->addAttr(UsedAttr::CreateImplicit(S.Context));
65257330f729Sjoerg }
65267330f729Sjoerg 
handleMipsInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)65277330f729Sjoerg static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
65287330f729Sjoerg   // Only one optional argument permitted.
65297330f729Sjoerg   if (AL.getNumArgs() > 1) {
65307330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
65317330f729Sjoerg     return;
65327330f729Sjoerg   }
65337330f729Sjoerg 
65347330f729Sjoerg   StringRef Str;
65357330f729Sjoerg   SourceLocation ArgLoc;
65367330f729Sjoerg 
65377330f729Sjoerg   if (AL.getNumArgs() == 0)
65387330f729Sjoerg     Str = "";
65397330f729Sjoerg   else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
65407330f729Sjoerg     return;
65417330f729Sjoerg 
65427330f729Sjoerg   // Semantic checks for a function with the 'interrupt' attribute for MIPS:
65437330f729Sjoerg   // a) Must be a function.
65447330f729Sjoerg   // b) Must have no parameters.
65457330f729Sjoerg   // c) Must have the 'void' return type.
65467330f729Sjoerg   // d) Cannot have the 'mips16' attribute, as that instruction set
65477330f729Sjoerg   //    lacks the 'eret' instruction.
65487330f729Sjoerg   // e) The attribute itself must either have no argument or one of the
65497330f729Sjoerg   //    valid interrupt types, see [MipsInterruptDocs].
65507330f729Sjoerg 
65517330f729Sjoerg   if (!isFunctionOrMethod(D)) {
65527330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
65537330f729Sjoerg         << "'interrupt'" << ExpectedFunctionOrMethod;
65547330f729Sjoerg     return;
65557330f729Sjoerg   }
65567330f729Sjoerg 
65577330f729Sjoerg   if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
65587330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
65597330f729Sjoerg         << /*MIPS*/ 0 << 0;
65607330f729Sjoerg     return;
65617330f729Sjoerg   }
65627330f729Sjoerg 
65637330f729Sjoerg   if (!getFunctionOrMethodResultType(D)->isVoidType()) {
65647330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
65657330f729Sjoerg         << /*MIPS*/ 0 << 1;
65667330f729Sjoerg     return;
65677330f729Sjoerg   }
65687330f729Sjoerg 
6569*e038c9c4Sjoerg   // We still have to do this manually because the Interrupt attributes are
6570*e038c9c4Sjoerg   // a bit special due to sharing their spellings across targets.
65717330f729Sjoerg   if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL))
65727330f729Sjoerg     return;
65737330f729Sjoerg 
65747330f729Sjoerg   MipsInterruptAttr::InterruptType Kind;
65757330f729Sjoerg   if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
65767330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
65777330f729Sjoerg         << AL << "'" + std::string(Str) + "'";
65787330f729Sjoerg     return;
65797330f729Sjoerg   }
65807330f729Sjoerg 
65817330f729Sjoerg   D->addAttr(::new (S.Context) MipsInterruptAttr(S.Context, AL, Kind));
65827330f729Sjoerg }
65837330f729Sjoerg 
handleM68kInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)6584*e038c9c4Sjoerg static void handleM68kInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6585*e038c9c4Sjoerg   if (!AL.checkExactlyNumArgs(S, 1))
6586*e038c9c4Sjoerg     return;
6587*e038c9c4Sjoerg 
6588*e038c9c4Sjoerg   if (!AL.isArgExpr(0)) {
6589*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
6590*e038c9c4Sjoerg         << AL << AANT_ArgumentIntegerConstant;
6591*e038c9c4Sjoerg     return;
6592*e038c9c4Sjoerg   }
6593*e038c9c4Sjoerg 
6594*e038c9c4Sjoerg   // FIXME: Check for decl - it should be void ()(void).
6595*e038c9c4Sjoerg 
6596*e038c9c4Sjoerg   Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
6597*e038c9c4Sjoerg   auto MaybeNumParams = NumParamsExpr->getIntegerConstantExpr(S.Context);
6598*e038c9c4Sjoerg   if (!MaybeNumParams) {
6599*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
6600*e038c9c4Sjoerg         << AL << AANT_ArgumentIntegerConstant
6601*e038c9c4Sjoerg         << NumParamsExpr->getSourceRange();
6602*e038c9c4Sjoerg     return;
6603*e038c9c4Sjoerg   }
6604*e038c9c4Sjoerg 
6605*e038c9c4Sjoerg   unsigned Num = MaybeNumParams->getLimitedValue(255);
6606*e038c9c4Sjoerg   if ((Num & 1) || Num > 30) {
6607*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
6608*e038c9c4Sjoerg         << AL << (int)MaybeNumParams->getSExtValue()
6609*e038c9c4Sjoerg         << NumParamsExpr->getSourceRange();
6610*e038c9c4Sjoerg     return;
6611*e038c9c4Sjoerg   }
6612*e038c9c4Sjoerg 
6613*e038c9c4Sjoerg   D->addAttr(::new (S.Context) M68kInterruptAttr(S.Context, AL, Num));
6614*e038c9c4Sjoerg   D->addAttr(UsedAttr::CreateImplicit(S.Context));
6615*e038c9c4Sjoerg }
6616*e038c9c4Sjoerg 
handleAnyX86InterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)66177330f729Sjoerg static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
66187330f729Sjoerg   // Semantic checks for a function with the 'interrupt' attribute.
66197330f729Sjoerg   // a) Must be a function.
66207330f729Sjoerg   // b) Must have the 'void' return type.
66217330f729Sjoerg   // c) Must take 1 or 2 arguments.
66227330f729Sjoerg   // d) The 1st argument must be a pointer.
66237330f729Sjoerg   // e) The 2nd argument (if any) must be an unsigned integer.
66247330f729Sjoerg   if (!isFunctionOrMethod(D) || !hasFunctionProto(D) || isInstanceMethod(D) ||
66257330f729Sjoerg       CXXMethodDecl::isStaticOverloadedOperator(
66267330f729Sjoerg           cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) {
66277330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
66287330f729Sjoerg         << AL << ExpectedFunctionWithProtoType;
66297330f729Sjoerg     return;
66307330f729Sjoerg   }
66317330f729Sjoerg   // Interrupt handler must have void return type.
66327330f729Sjoerg   if (!getFunctionOrMethodResultType(D)->isVoidType()) {
66337330f729Sjoerg     S.Diag(getFunctionOrMethodResultSourceRange(D).getBegin(),
66347330f729Sjoerg            diag::err_anyx86_interrupt_attribute)
66357330f729Sjoerg         << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
66367330f729Sjoerg                 ? 0
66377330f729Sjoerg                 : 1)
66387330f729Sjoerg         << 0;
66397330f729Sjoerg     return;
66407330f729Sjoerg   }
66417330f729Sjoerg   // Interrupt handler must have 1 or 2 parameters.
66427330f729Sjoerg   unsigned NumParams = getFunctionOrMethodNumParams(D);
66437330f729Sjoerg   if (NumParams < 1 || NumParams > 2) {
66447330f729Sjoerg     S.Diag(D->getBeginLoc(), diag::err_anyx86_interrupt_attribute)
66457330f729Sjoerg         << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
66467330f729Sjoerg                 ? 0
66477330f729Sjoerg                 : 1)
66487330f729Sjoerg         << 1;
66497330f729Sjoerg     return;
66507330f729Sjoerg   }
66517330f729Sjoerg   // The first argument must be a pointer.
66527330f729Sjoerg   if (!getFunctionOrMethodParamType(D, 0)->isPointerType()) {
66537330f729Sjoerg     S.Diag(getFunctionOrMethodParamRange(D, 0).getBegin(),
66547330f729Sjoerg            diag::err_anyx86_interrupt_attribute)
66557330f729Sjoerg         << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
66567330f729Sjoerg                 ? 0
66577330f729Sjoerg                 : 1)
66587330f729Sjoerg         << 2;
66597330f729Sjoerg     return;
66607330f729Sjoerg   }
66617330f729Sjoerg   // The second argument, if present, must be an unsigned integer.
66627330f729Sjoerg   unsigned TypeSize =
66637330f729Sjoerg       S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64
66647330f729Sjoerg           ? 64
66657330f729Sjoerg           : 32;
66667330f729Sjoerg   if (NumParams == 2 &&
66677330f729Sjoerg       (!getFunctionOrMethodParamType(D, 1)->isUnsignedIntegerType() ||
66687330f729Sjoerg        S.Context.getTypeSize(getFunctionOrMethodParamType(D, 1)) != TypeSize)) {
66697330f729Sjoerg     S.Diag(getFunctionOrMethodParamRange(D, 1).getBegin(),
66707330f729Sjoerg            diag::err_anyx86_interrupt_attribute)
66717330f729Sjoerg         << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
66727330f729Sjoerg                 ? 0
66737330f729Sjoerg                 : 1)
66747330f729Sjoerg         << 3 << S.Context.getIntTypeForBitwidth(TypeSize, /*Signed=*/false);
66757330f729Sjoerg     return;
66767330f729Sjoerg   }
66777330f729Sjoerg   D->addAttr(::new (S.Context) AnyX86InterruptAttr(S.Context, AL));
66787330f729Sjoerg   D->addAttr(UsedAttr::CreateImplicit(S.Context));
66797330f729Sjoerg }
66807330f729Sjoerg 
handleAVRInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)66817330f729Sjoerg static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
66827330f729Sjoerg   if (!isFunctionOrMethod(D)) {
66837330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
66847330f729Sjoerg         << "'interrupt'" << ExpectedFunction;
66857330f729Sjoerg     return;
66867330f729Sjoerg   }
66877330f729Sjoerg 
6688*e038c9c4Sjoerg   if (!AL.checkExactlyNumArgs(S, 0))
66897330f729Sjoerg     return;
66907330f729Sjoerg 
66917330f729Sjoerg   handleSimpleAttribute<AVRInterruptAttr>(S, D, AL);
66927330f729Sjoerg }
66937330f729Sjoerg 
handleAVRSignalAttr(Sema & S,Decl * D,const ParsedAttr & AL)66947330f729Sjoerg static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
66957330f729Sjoerg   if (!isFunctionOrMethod(D)) {
66967330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
66977330f729Sjoerg         << "'signal'" << ExpectedFunction;
66987330f729Sjoerg     return;
66997330f729Sjoerg   }
67007330f729Sjoerg 
6701*e038c9c4Sjoerg   if (!AL.checkExactlyNumArgs(S, 0))
67027330f729Sjoerg     return;
67037330f729Sjoerg 
67047330f729Sjoerg   handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
67057330f729Sjoerg }
67067330f729Sjoerg 
handleBPFPreserveAIRecord(Sema & S,RecordDecl * RD)6707*e038c9c4Sjoerg static void handleBPFPreserveAIRecord(Sema &S, RecordDecl *RD) {
6708*e038c9c4Sjoerg   // Add preserve_access_index attribute to all fields and inner records.
6709*e038c9c4Sjoerg   for (auto D : RD->decls()) {
6710*e038c9c4Sjoerg     if (D->hasAttr<BPFPreserveAccessIndexAttr>())
6711*e038c9c4Sjoerg       continue;
6712*e038c9c4Sjoerg 
6713*e038c9c4Sjoerg     D->addAttr(BPFPreserveAccessIndexAttr::CreateImplicit(S.Context));
6714*e038c9c4Sjoerg     if (auto *Rec = dyn_cast<RecordDecl>(D))
6715*e038c9c4Sjoerg       handleBPFPreserveAIRecord(S, Rec);
6716*e038c9c4Sjoerg   }
6717*e038c9c4Sjoerg }
6718*e038c9c4Sjoerg 
handleBPFPreserveAccessIndexAttr(Sema & S,Decl * D,const ParsedAttr & AL)6719*e038c9c4Sjoerg static void handleBPFPreserveAccessIndexAttr(Sema &S, Decl *D,
6720*e038c9c4Sjoerg     const ParsedAttr &AL) {
6721*e038c9c4Sjoerg   auto *Rec = cast<RecordDecl>(D);
6722*e038c9c4Sjoerg   handleBPFPreserveAIRecord(S, Rec);
6723*e038c9c4Sjoerg   Rec->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL));
6724*e038c9c4Sjoerg }
6725*e038c9c4Sjoerg 
handleWebAssemblyExportNameAttr(Sema & S,Decl * D,const ParsedAttr & AL)6726*e038c9c4Sjoerg static void handleWebAssemblyExportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
67277330f729Sjoerg   if (!isFunctionOrMethod(D)) {
67287330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
6729*e038c9c4Sjoerg         << "'export_name'" << ExpectedFunction;
67307330f729Sjoerg     return;
67317330f729Sjoerg   }
67327330f729Sjoerg 
67337330f729Sjoerg   auto *FD = cast<FunctionDecl>(D);
67347330f729Sjoerg   if (FD->isThisDeclarationADefinition()) {
67357330f729Sjoerg     S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
67367330f729Sjoerg     return;
67377330f729Sjoerg   }
67387330f729Sjoerg 
67397330f729Sjoerg   StringRef Str;
67407330f729Sjoerg   SourceLocation ArgLoc;
67417330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
67427330f729Sjoerg     return;
67437330f729Sjoerg 
6744*e038c9c4Sjoerg   D->addAttr(::new (S.Context) WebAssemblyExportNameAttr(S.Context, AL, Str));
6745*e038c9c4Sjoerg   D->addAttr(UsedAttr::CreateImplicit(S.Context));
6746*e038c9c4Sjoerg }
6747*e038c9c4Sjoerg 
6748*e038c9c4Sjoerg WebAssemblyImportModuleAttr *
mergeImportModuleAttr(Decl * D,const WebAssemblyImportModuleAttr & AL)6749*e038c9c4Sjoerg Sema::mergeImportModuleAttr(Decl *D, const WebAssemblyImportModuleAttr &AL) {
6750*e038c9c4Sjoerg   auto *FD = cast<FunctionDecl>(D);
6751*e038c9c4Sjoerg 
6752*e038c9c4Sjoerg   if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportModuleAttr>()) {
6753*e038c9c4Sjoerg     if (ExistingAttr->getImportModule() == AL.getImportModule())
6754*e038c9c4Sjoerg       return nullptr;
6755*e038c9c4Sjoerg     Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import) << 0
6756*e038c9c4Sjoerg       << ExistingAttr->getImportModule() << AL.getImportModule();
6757*e038c9c4Sjoerg     Diag(AL.getLoc(), diag::note_previous_attribute);
6758*e038c9c4Sjoerg     return nullptr;
6759*e038c9c4Sjoerg   }
6760*e038c9c4Sjoerg   if (FD->hasBody()) {
6761*e038c9c4Sjoerg     Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
6762*e038c9c4Sjoerg     return nullptr;
6763*e038c9c4Sjoerg   }
6764*e038c9c4Sjoerg   return ::new (Context) WebAssemblyImportModuleAttr(Context, AL,
6765*e038c9c4Sjoerg                                                      AL.getImportModule());
6766*e038c9c4Sjoerg }
6767*e038c9c4Sjoerg 
6768*e038c9c4Sjoerg WebAssemblyImportNameAttr *
mergeImportNameAttr(Decl * D,const WebAssemblyImportNameAttr & AL)6769*e038c9c4Sjoerg Sema::mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL) {
6770*e038c9c4Sjoerg   auto *FD = cast<FunctionDecl>(D);
6771*e038c9c4Sjoerg 
6772*e038c9c4Sjoerg   if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportNameAttr>()) {
6773*e038c9c4Sjoerg     if (ExistingAttr->getImportName() == AL.getImportName())
6774*e038c9c4Sjoerg       return nullptr;
6775*e038c9c4Sjoerg     Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import) << 1
6776*e038c9c4Sjoerg       << ExistingAttr->getImportName() << AL.getImportName();
6777*e038c9c4Sjoerg     Diag(AL.getLoc(), diag::note_previous_attribute);
6778*e038c9c4Sjoerg     return nullptr;
6779*e038c9c4Sjoerg   }
6780*e038c9c4Sjoerg   if (FD->hasBody()) {
6781*e038c9c4Sjoerg     Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
6782*e038c9c4Sjoerg     return nullptr;
6783*e038c9c4Sjoerg   }
6784*e038c9c4Sjoerg   return ::new (Context) WebAssemblyImportNameAttr(Context, AL,
6785*e038c9c4Sjoerg                                                    AL.getImportName());
6786*e038c9c4Sjoerg }
6787*e038c9c4Sjoerg 
6788*e038c9c4Sjoerg static void
handleWebAssemblyImportModuleAttr(Sema & S,Decl * D,const ParsedAttr & AL)6789*e038c9c4Sjoerg handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6790*e038c9c4Sjoerg   auto *FD = cast<FunctionDecl>(D);
6791*e038c9c4Sjoerg 
6792*e038c9c4Sjoerg   StringRef Str;
6793*e038c9c4Sjoerg   SourceLocation ArgLoc;
6794*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
6795*e038c9c4Sjoerg     return;
6796*e038c9c4Sjoerg   if (FD->hasBody()) {
6797*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
6798*e038c9c4Sjoerg     return;
6799*e038c9c4Sjoerg   }
6800*e038c9c4Sjoerg 
68017330f729Sjoerg   FD->addAttr(::new (S.Context)
68027330f729Sjoerg                   WebAssemblyImportModuleAttr(S.Context, AL, Str));
68037330f729Sjoerg }
68047330f729Sjoerg 
6805*e038c9c4Sjoerg static void
handleWebAssemblyImportNameAttr(Sema & S,Decl * D,const ParsedAttr & AL)6806*e038c9c4Sjoerg handleWebAssemblyImportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
68077330f729Sjoerg   auto *FD = cast<FunctionDecl>(D);
68087330f729Sjoerg 
68097330f729Sjoerg   StringRef Str;
68107330f729Sjoerg   SourceLocation ArgLoc;
68117330f729Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
68127330f729Sjoerg     return;
6813*e038c9c4Sjoerg   if (FD->hasBody()) {
6814*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
6815*e038c9c4Sjoerg     return;
6816*e038c9c4Sjoerg   }
68177330f729Sjoerg 
68187330f729Sjoerg   FD->addAttr(::new (S.Context) WebAssemblyImportNameAttr(S.Context, AL, Str));
68197330f729Sjoerg }
68207330f729Sjoerg 
handleRISCVInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)68217330f729Sjoerg static void handleRISCVInterruptAttr(Sema &S, Decl *D,
68227330f729Sjoerg                                      const ParsedAttr &AL) {
68237330f729Sjoerg   // Warn about repeated attributes.
68247330f729Sjoerg   if (const auto *A = D->getAttr<RISCVInterruptAttr>()) {
68257330f729Sjoerg     S.Diag(AL.getRange().getBegin(),
68267330f729Sjoerg       diag::warn_riscv_repeated_interrupt_attribute);
68277330f729Sjoerg     S.Diag(A->getLocation(), diag::note_riscv_repeated_interrupt_attribute);
68287330f729Sjoerg     return;
68297330f729Sjoerg   }
68307330f729Sjoerg 
68317330f729Sjoerg   // Check the attribute argument. Argument is optional.
6832*e038c9c4Sjoerg   if (!AL.checkAtMostNumArgs(S, 1))
68337330f729Sjoerg     return;
68347330f729Sjoerg 
68357330f729Sjoerg   StringRef Str;
68367330f729Sjoerg   SourceLocation ArgLoc;
68377330f729Sjoerg 
68387330f729Sjoerg   // 'machine'is the default interrupt mode.
68397330f729Sjoerg   if (AL.getNumArgs() == 0)
68407330f729Sjoerg     Str = "machine";
68417330f729Sjoerg   else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
68427330f729Sjoerg     return;
68437330f729Sjoerg 
68447330f729Sjoerg   // Semantic checks for a function with the 'interrupt' attribute:
68457330f729Sjoerg   // - Must be a function.
68467330f729Sjoerg   // - Must have no parameters.
68477330f729Sjoerg   // - Must have the 'void' return type.
68487330f729Sjoerg   // - The attribute itself must either have no argument or one of the
68497330f729Sjoerg   //   valid interrupt types, see [RISCVInterruptDocs].
68507330f729Sjoerg 
68517330f729Sjoerg   if (D->getFunctionType() == nullptr) {
68527330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
68537330f729Sjoerg       << "'interrupt'" << ExpectedFunction;
68547330f729Sjoerg     return;
68557330f729Sjoerg   }
68567330f729Sjoerg 
68577330f729Sjoerg   if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
68587330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
68597330f729Sjoerg       << /*RISC-V*/ 2 << 0;
68607330f729Sjoerg     return;
68617330f729Sjoerg   }
68627330f729Sjoerg 
68637330f729Sjoerg   if (!getFunctionOrMethodResultType(D)->isVoidType()) {
68647330f729Sjoerg     S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
68657330f729Sjoerg       << /*RISC-V*/ 2 << 1;
68667330f729Sjoerg     return;
68677330f729Sjoerg   }
68687330f729Sjoerg 
68697330f729Sjoerg   RISCVInterruptAttr::InterruptType Kind;
68707330f729Sjoerg   if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
68717330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
68727330f729Sjoerg                                                                  << ArgLoc;
68737330f729Sjoerg     return;
68747330f729Sjoerg   }
68757330f729Sjoerg 
68767330f729Sjoerg   D->addAttr(::new (S.Context) RISCVInterruptAttr(S.Context, AL, Kind));
68777330f729Sjoerg }
68787330f729Sjoerg 
handleInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)68797330f729Sjoerg static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
68807330f729Sjoerg   // Dispatch the interrupt attribute based on the current target.
68817330f729Sjoerg   switch (S.Context.getTargetInfo().getTriple().getArch()) {
68827330f729Sjoerg   case llvm::Triple::msp430:
68837330f729Sjoerg     handleMSP430InterruptAttr(S, D, AL);
68847330f729Sjoerg     break;
68857330f729Sjoerg   case llvm::Triple::mipsel:
68867330f729Sjoerg   case llvm::Triple::mips:
68877330f729Sjoerg     handleMipsInterruptAttr(S, D, AL);
68887330f729Sjoerg     break;
6889*e038c9c4Sjoerg   case llvm::Triple::m68k:
6890*e038c9c4Sjoerg     handleM68kInterruptAttr(S, D, AL);
6891*e038c9c4Sjoerg     break;
68927330f729Sjoerg   case llvm::Triple::x86:
68937330f729Sjoerg   case llvm::Triple::x86_64:
68947330f729Sjoerg     handleAnyX86InterruptAttr(S, D, AL);
68957330f729Sjoerg     break;
68967330f729Sjoerg   case llvm::Triple::avr:
68977330f729Sjoerg     handleAVRInterruptAttr(S, D, AL);
68987330f729Sjoerg     break;
68997330f729Sjoerg   case llvm::Triple::riscv32:
69007330f729Sjoerg   case llvm::Triple::riscv64:
69017330f729Sjoerg     handleRISCVInterruptAttr(S, D, AL);
69027330f729Sjoerg     break;
69037330f729Sjoerg   default:
69047330f729Sjoerg     handleARMInterruptAttr(S, D, AL);
69057330f729Sjoerg     break;
69067330f729Sjoerg   }
69077330f729Sjoerg }
69087330f729Sjoerg 
69097330f729Sjoerg static bool
checkAMDGPUFlatWorkGroupSizeArguments(Sema & S,Expr * MinExpr,Expr * MaxExpr,const AMDGPUFlatWorkGroupSizeAttr & Attr)69107330f729Sjoerg checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr,
69117330f729Sjoerg                                       const AMDGPUFlatWorkGroupSizeAttr &Attr) {
69127330f729Sjoerg   // Accept template arguments for now as they depend on something else.
69137330f729Sjoerg   // We'll get to check them when they eventually get instantiated.
69147330f729Sjoerg   if (MinExpr->isValueDependent() || MaxExpr->isValueDependent())
69157330f729Sjoerg     return false;
69167330f729Sjoerg 
69177330f729Sjoerg   uint32_t Min = 0;
69187330f729Sjoerg   if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0))
69197330f729Sjoerg     return true;
69207330f729Sjoerg 
69217330f729Sjoerg   uint32_t Max = 0;
69227330f729Sjoerg   if (!checkUInt32Argument(S, Attr, MaxExpr, Max, 1))
69237330f729Sjoerg     return true;
69247330f729Sjoerg 
69257330f729Sjoerg   if (Min == 0 && Max != 0) {
69267330f729Sjoerg     S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
69277330f729Sjoerg         << &Attr << 0;
69287330f729Sjoerg     return true;
69297330f729Sjoerg   }
69307330f729Sjoerg   if (Min > Max) {
69317330f729Sjoerg     S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
69327330f729Sjoerg         << &Attr << 1;
69337330f729Sjoerg     return true;
69347330f729Sjoerg   }
69357330f729Sjoerg 
69367330f729Sjoerg   return false;
69377330f729Sjoerg }
69387330f729Sjoerg 
addAMDGPUFlatWorkGroupSizeAttr(Decl * D,const AttributeCommonInfo & CI,Expr * MinExpr,Expr * MaxExpr)69397330f729Sjoerg void Sema::addAMDGPUFlatWorkGroupSizeAttr(Decl *D,
69407330f729Sjoerg                                           const AttributeCommonInfo &CI,
69417330f729Sjoerg                                           Expr *MinExpr, Expr *MaxExpr) {
69427330f729Sjoerg   AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
69437330f729Sjoerg 
69447330f729Sjoerg   if (checkAMDGPUFlatWorkGroupSizeArguments(*this, MinExpr, MaxExpr, TmpAttr))
69457330f729Sjoerg     return;
69467330f729Sjoerg 
69477330f729Sjoerg   D->addAttr(::new (Context)
69487330f729Sjoerg                  AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr));
69497330f729Sjoerg }
69507330f729Sjoerg 
handleAMDGPUFlatWorkGroupSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)69517330f729Sjoerg static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
69527330f729Sjoerg                                               const ParsedAttr &AL) {
69537330f729Sjoerg   Expr *MinExpr = AL.getArgAsExpr(0);
69547330f729Sjoerg   Expr *MaxExpr = AL.getArgAsExpr(1);
69557330f729Sjoerg 
69567330f729Sjoerg   S.addAMDGPUFlatWorkGroupSizeAttr(D, AL, MinExpr, MaxExpr);
69577330f729Sjoerg }
69587330f729Sjoerg 
checkAMDGPUWavesPerEUArguments(Sema & S,Expr * MinExpr,Expr * MaxExpr,const AMDGPUWavesPerEUAttr & Attr)69597330f729Sjoerg static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr,
69607330f729Sjoerg                                            Expr *MaxExpr,
69617330f729Sjoerg                                            const AMDGPUWavesPerEUAttr &Attr) {
69627330f729Sjoerg   if (S.DiagnoseUnexpandedParameterPack(MinExpr) ||
69637330f729Sjoerg       (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr)))
69647330f729Sjoerg     return true;
69657330f729Sjoerg 
69667330f729Sjoerg   // Accept template arguments for now as they depend on something else.
69677330f729Sjoerg   // We'll get to check them when they eventually get instantiated.
69687330f729Sjoerg   if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent()))
69697330f729Sjoerg     return false;
69707330f729Sjoerg 
69717330f729Sjoerg   uint32_t Min = 0;
69727330f729Sjoerg   if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0))
69737330f729Sjoerg     return true;
69747330f729Sjoerg 
69757330f729Sjoerg   uint32_t Max = 0;
69767330f729Sjoerg   if (MaxExpr && !checkUInt32Argument(S, Attr, MaxExpr, Max, 1))
69777330f729Sjoerg     return true;
69787330f729Sjoerg 
69797330f729Sjoerg   if (Min == 0 && Max != 0) {
69807330f729Sjoerg     S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
69817330f729Sjoerg         << &Attr << 0;
69827330f729Sjoerg     return true;
69837330f729Sjoerg   }
69847330f729Sjoerg   if (Max != 0 && Min > Max) {
69857330f729Sjoerg     S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
69867330f729Sjoerg         << &Attr << 1;
69877330f729Sjoerg     return true;
69887330f729Sjoerg   }
69897330f729Sjoerg 
69907330f729Sjoerg   return false;
69917330f729Sjoerg }
69927330f729Sjoerg 
addAMDGPUWavesPerEUAttr(Decl * D,const AttributeCommonInfo & CI,Expr * MinExpr,Expr * MaxExpr)69937330f729Sjoerg void Sema::addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
69947330f729Sjoerg                                    Expr *MinExpr, Expr *MaxExpr) {
69957330f729Sjoerg   AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
69967330f729Sjoerg 
69977330f729Sjoerg   if (checkAMDGPUWavesPerEUArguments(*this, MinExpr, MaxExpr, TmpAttr))
69987330f729Sjoerg     return;
69997330f729Sjoerg 
70007330f729Sjoerg   D->addAttr(::new (Context)
70017330f729Sjoerg                  AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr));
70027330f729Sjoerg }
70037330f729Sjoerg 
handleAMDGPUWavesPerEUAttr(Sema & S,Decl * D,const ParsedAttr & AL)70047330f729Sjoerg static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7005*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
70067330f729Sjoerg     return;
70077330f729Sjoerg 
70087330f729Sjoerg   Expr *MinExpr = AL.getArgAsExpr(0);
70097330f729Sjoerg   Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
70107330f729Sjoerg 
70117330f729Sjoerg   S.addAMDGPUWavesPerEUAttr(D, AL, MinExpr, MaxExpr);
70127330f729Sjoerg }
70137330f729Sjoerg 
handleAMDGPUNumSGPRAttr(Sema & S,Decl * D,const ParsedAttr & AL)70147330f729Sjoerg static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
70157330f729Sjoerg   uint32_t NumSGPR = 0;
70167330f729Sjoerg   Expr *NumSGPRExpr = AL.getArgAsExpr(0);
70177330f729Sjoerg   if (!checkUInt32Argument(S, AL, NumSGPRExpr, NumSGPR))
70187330f729Sjoerg     return;
70197330f729Sjoerg 
70207330f729Sjoerg   D->addAttr(::new (S.Context) AMDGPUNumSGPRAttr(S.Context, AL, NumSGPR));
70217330f729Sjoerg }
70227330f729Sjoerg 
handleAMDGPUNumVGPRAttr(Sema & S,Decl * D,const ParsedAttr & AL)70237330f729Sjoerg static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
70247330f729Sjoerg   uint32_t NumVGPR = 0;
70257330f729Sjoerg   Expr *NumVGPRExpr = AL.getArgAsExpr(0);
70267330f729Sjoerg   if (!checkUInt32Argument(S, AL, NumVGPRExpr, NumVGPR))
70277330f729Sjoerg     return;
70287330f729Sjoerg 
70297330f729Sjoerg   D->addAttr(::new (S.Context) AMDGPUNumVGPRAttr(S.Context, AL, NumVGPR));
70307330f729Sjoerg }
70317330f729Sjoerg 
handleX86ForceAlignArgPointerAttr(Sema & S,Decl * D,const ParsedAttr & AL)70327330f729Sjoerg static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
70337330f729Sjoerg                                               const ParsedAttr &AL) {
70347330f729Sjoerg   // If we try to apply it to a function pointer, don't warn, but don't
70357330f729Sjoerg   // do anything, either. It doesn't matter anyway, because there's nothing
70367330f729Sjoerg   // special about calling a force_align_arg_pointer function.
70377330f729Sjoerg   const auto *VD = dyn_cast<ValueDecl>(D);
70387330f729Sjoerg   if (VD && VD->getType()->isFunctionPointerType())
70397330f729Sjoerg     return;
70407330f729Sjoerg   // Also don't warn on function pointer typedefs.
70417330f729Sjoerg   const auto *TD = dyn_cast<TypedefNameDecl>(D);
70427330f729Sjoerg   if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
70437330f729Sjoerg     TD->getUnderlyingType()->isFunctionType()))
70447330f729Sjoerg     return;
70457330f729Sjoerg   // Attribute can only be applied to function types.
70467330f729Sjoerg   if (!isa<FunctionDecl>(D)) {
70477330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
70487330f729Sjoerg         << AL << ExpectedFunction;
70497330f729Sjoerg     return;
70507330f729Sjoerg   }
70517330f729Sjoerg 
70527330f729Sjoerg   D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(S.Context, AL));
70537330f729Sjoerg }
70547330f729Sjoerg 
handleLayoutVersion(Sema & S,Decl * D,const ParsedAttr & AL)70557330f729Sjoerg static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) {
70567330f729Sjoerg   uint32_t Version;
70577330f729Sjoerg   Expr *VersionExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
70587330f729Sjoerg   if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Version))
70597330f729Sjoerg     return;
70607330f729Sjoerg 
70617330f729Sjoerg   // TODO: Investigate what happens with the next major version of MSVC.
70627330f729Sjoerg   if (Version != LangOptions::MSVC2015 / 100) {
70637330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
70647330f729Sjoerg         << AL << Version << VersionExpr->getSourceRange();
70657330f729Sjoerg     return;
70667330f729Sjoerg   }
70677330f729Sjoerg 
70687330f729Sjoerg   // The attribute expects a "major" version number like 19, but new versions of
70697330f729Sjoerg   // MSVC have moved to updating the "minor", or less significant numbers, so we
70707330f729Sjoerg   // have to multiply by 100 now.
70717330f729Sjoerg   Version *= 100;
70727330f729Sjoerg 
70737330f729Sjoerg   D->addAttr(::new (S.Context) LayoutVersionAttr(S.Context, AL, Version));
70747330f729Sjoerg }
70757330f729Sjoerg 
mergeDLLImportAttr(Decl * D,const AttributeCommonInfo & CI)70767330f729Sjoerg DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D,
70777330f729Sjoerg                                         const AttributeCommonInfo &CI) {
70787330f729Sjoerg   if (D->hasAttr<DLLExportAttr>()) {
70797330f729Sjoerg     Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'dllimport'";
70807330f729Sjoerg     return nullptr;
70817330f729Sjoerg   }
70827330f729Sjoerg 
70837330f729Sjoerg   if (D->hasAttr<DLLImportAttr>())
70847330f729Sjoerg     return nullptr;
70857330f729Sjoerg 
70867330f729Sjoerg   return ::new (Context) DLLImportAttr(Context, CI);
70877330f729Sjoerg }
70887330f729Sjoerg 
mergeDLLExportAttr(Decl * D,const AttributeCommonInfo & CI)70897330f729Sjoerg DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D,
70907330f729Sjoerg                                         const AttributeCommonInfo &CI) {
70917330f729Sjoerg   if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
70927330f729Sjoerg     Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import;
70937330f729Sjoerg     D->dropAttr<DLLImportAttr>();
70947330f729Sjoerg   }
70957330f729Sjoerg 
70967330f729Sjoerg   if (D->hasAttr<DLLExportAttr>())
70977330f729Sjoerg     return nullptr;
70987330f729Sjoerg 
70997330f729Sjoerg   return ::new (Context) DLLExportAttr(Context, CI);
71007330f729Sjoerg }
71017330f729Sjoerg 
handleDLLAttr(Sema & S,Decl * D,const ParsedAttr & A)71027330f729Sjoerg static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
71037330f729Sjoerg   if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
7104*e038c9c4Sjoerg       (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) {
71057330f729Sjoerg     S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A;
71067330f729Sjoerg     return;
71077330f729Sjoerg   }
71087330f729Sjoerg 
71097330f729Sjoerg   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
71107330f729Sjoerg     if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport &&
7111*e038c9c4Sjoerg         !(S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) {
71127330f729Sjoerg       // MinGW doesn't allow dllimport on inline functions.
71137330f729Sjoerg       S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
71147330f729Sjoerg           << A;
71157330f729Sjoerg       return;
71167330f729Sjoerg     }
71177330f729Sjoerg   }
71187330f729Sjoerg 
71197330f729Sjoerg   if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
7120*e038c9c4Sjoerg     if ((S.Context.getTargetInfo().shouldDLLImportComdatSymbols()) &&
71217330f729Sjoerg         MD->getParent()->isLambda()) {
71227330f729Sjoerg       S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A;
71237330f729Sjoerg       return;
71247330f729Sjoerg     }
71257330f729Sjoerg   }
71267330f729Sjoerg 
71277330f729Sjoerg   Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport
71287330f729Sjoerg                       ? (Attr *)S.mergeDLLExportAttr(D, A)
71297330f729Sjoerg                       : (Attr *)S.mergeDLLImportAttr(D, A);
71307330f729Sjoerg   if (NewAttr)
71317330f729Sjoerg     D->addAttr(NewAttr);
71327330f729Sjoerg }
71337330f729Sjoerg 
71347330f729Sjoerg MSInheritanceAttr *
mergeMSInheritanceAttr(Decl * D,const AttributeCommonInfo & CI,bool BestCase,MSInheritanceModel Model)71357330f729Sjoerg Sema::mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI,
71367330f729Sjoerg                              bool BestCase,
7137*e038c9c4Sjoerg                              MSInheritanceModel Model) {
71387330f729Sjoerg   if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) {
7139*e038c9c4Sjoerg     if (IA->getInheritanceModel() == Model)
71407330f729Sjoerg       return nullptr;
71417330f729Sjoerg     Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance)
71427330f729Sjoerg         << 1 /*previous declaration*/;
71437330f729Sjoerg     Diag(CI.getLoc(), diag::note_previous_ms_inheritance);
71447330f729Sjoerg     D->dropAttr<MSInheritanceAttr>();
71457330f729Sjoerg   }
71467330f729Sjoerg 
71477330f729Sjoerg   auto *RD = cast<CXXRecordDecl>(D);
71487330f729Sjoerg   if (RD->hasDefinition()) {
71497330f729Sjoerg     if (checkMSInheritanceAttrOnDefinition(RD, CI.getRange(), BestCase,
7150*e038c9c4Sjoerg                                            Model)) {
71517330f729Sjoerg       return nullptr;
71527330f729Sjoerg     }
71537330f729Sjoerg   } else {
71547330f729Sjoerg     if (isa<ClassTemplatePartialSpecializationDecl>(RD)) {
71557330f729Sjoerg       Diag(CI.getLoc(), diag::warn_ignored_ms_inheritance)
71567330f729Sjoerg           << 1 /*partial specialization*/;
71577330f729Sjoerg       return nullptr;
71587330f729Sjoerg     }
71597330f729Sjoerg     if (RD->getDescribedClassTemplate()) {
71607330f729Sjoerg       Diag(CI.getLoc(), diag::warn_ignored_ms_inheritance)
71617330f729Sjoerg           << 0 /*primary template*/;
71627330f729Sjoerg       return nullptr;
71637330f729Sjoerg     }
71647330f729Sjoerg   }
71657330f729Sjoerg 
71667330f729Sjoerg   return ::new (Context) MSInheritanceAttr(Context, CI, BestCase);
71677330f729Sjoerg }
71687330f729Sjoerg 
handleCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)71697330f729Sjoerg static void handleCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
71707330f729Sjoerg   // The capability attributes take a single string parameter for the name of
71717330f729Sjoerg   // the capability they represent. The lockable attribute does not take any
71727330f729Sjoerg   // parameters. However, semantically, both attributes represent the same
71737330f729Sjoerg   // concept, and so they use the same semantic attribute. Eventually, the
71747330f729Sjoerg   // lockable attribute will be removed.
71757330f729Sjoerg   //
71767330f729Sjoerg   // For backward compatibility, any capability which has no specified string
71777330f729Sjoerg   // literal will be considered a "mutex."
71787330f729Sjoerg   StringRef N("mutex");
71797330f729Sjoerg   SourceLocation LiteralLoc;
71807330f729Sjoerg   if (AL.getKind() == ParsedAttr::AT_Capability &&
71817330f729Sjoerg       !S.checkStringLiteralArgumentAttr(AL, 0, N, &LiteralLoc))
71827330f729Sjoerg     return;
71837330f729Sjoerg 
71847330f729Sjoerg   D->addAttr(::new (S.Context) CapabilityAttr(S.Context, AL, N));
71857330f729Sjoerg }
71867330f729Sjoerg 
handleAssertCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)71877330f729Sjoerg static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
71887330f729Sjoerg   SmallVector<Expr*, 1> Args;
71897330f729Sjoerg   if (!checkLockFunAttrCommon(S, D, AL, Args))
71907330f729Sjoerg     return;
71917330f729Sjoerg 
71927330f729Sjoerg   D->addAttr(::new (S.Context)
71937330f729Sjoerg                  AssertCapabilityAttr(S.Context, AL, Args.data(), Args.size()));
71947330f729Sjoerg }
71957330f729Sjoerg 
handleAcquireCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)71967330f729Sjoerg static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
71977330f729Sjoerg                                         const ParsedAttr &AL) {
71987330f729Sjoerg   SmallVector<Expr*, 1> Args;
71997330f729Sjoerg   if (!checkLockFunAttrCommon(S, D, AL, Args))
72007330f729Sjoerg     return;
72017330f729Sjoerg 
72027330f729Sjoerg   D->addAttr(::new (S.Context) AcquireCapabilityAttr(S.Context, AL, Args.data(),
72037330f729Sjoerg                                                      Args.size()));
72047330f729Sjoerg }
72057330f729Sjoerg 
handleTryAcquireCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)72067330f729Sjoerg static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
72077330f729Sjoerg                                            const ParsedAttr &AL) {
72087330f729Sjoerg   SmallVector<Expr*, 2> Args;
72097330f729Sjoerg   if (!checkTryLockFunAttrCommon(S, D, AL, Args))
72107330f729Sjoerg     return;
72117330f729Sjoerg 
72127330f729Sjoerg   D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(
72137330f729Sjoerg       S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size()));
72147330f729Sjoerg }
72157330f729Sjoerg 
handleReleaseCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)72167330f729Sjoerg static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
72177330f729Sjoerg                                         const ParsedAttr &AL) {
72187330f729Sjoerg   // Check that all arguments are lockable objects.
72197330f729Sjoerg   SmallVector<Expr *, 1> Args;
72207330f729Sjoerg   checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, true);
72217330f729Sjoerg 
72227330f729Sjoerg   D->addAttr(::new (S.Context) ReleaseCapabilityAttr(S.Context, AL, Args.data(),
72237330f729Sjoerg                                                      Args.size()));
72247330f729Sjoerg }
72257330f729Sjoerg 
handleRequiresCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)72267330f729Sjoerg static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
72277330f729Sjoerg                                          const ParsedAttr &AL) {
7228*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1))
72297330f729Sjoerg     return;
72307330f729Sjoerg 
72317330f729Sjoerg   // check that all arguments are lockable objects
72327330f729Sjoerg   SmallVector<Expr*, 1> Args;
72337330f729Sjoerg   checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
72347330f729Sjoerg   if (Args.empty())
72357330f729Sjoerg     return;
72367330f729Sjoerg 
72377330f729Sjoerg   RequiresCapabilityAttr *RCA = ::new (S.Context)
72387330f729Sjoerg       RequiresCapabilityAttr(S.Context, AL, Args.data(), Args.size());
72397330f729Sjoerg 
72407330f729Sjoerg   D->addAttr(RCA);
72417330f729Sjoerg }
72427330f729Sjoerg 
handleDeprecatedAttr(Sema & S,Decl * D,const ParsedAttr & AL)72437330f729Sjoerg static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
72447330f729Sjoerg   if (const auto *NSD = dyn_cast<NamespaceDecl>(D)) {
72457330f729Sjoerg     if (NSD->isAnonymousNamespace()) {
72467330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_deprecated_anonymous_namespace);
72477330f729Sjoerg       // Do not want to attach the attribute to the namespace because that will
72487330f729Sjoerg       // cause confusing diagnostic reports for uses of declarations within the
72497330f729Sjoerg       // namespace.
72507330f729Sjoerg       return;
72517330f729Sjoerg     }
72527330f729Sjoerg   }
72537330f729Sjoerg 
72547330f729Sjoerg   // Handle the cases where the attribute has a text message.
72557330f729Sjoerg   StringRef Str, Replacement;
72567330f729Sjoerg   if (AL.isArgExpr(0) && AL.getArgAsExpr(0) &&
72577330f729Sjoerg       !S.checkStringLiteralArgumentAttr(AL, 0, Str))
72587330f729Sjoerg     return;
72597330f729Sjoerg 
72607330f729Sjoerg   // Only support a single optional message for Declspec and CXX11.
72617330f729Sjoerg   if (AL.isDeclspecAttribute() || AL.isCXX11Attribute())
7262*e038c9c4Sjoerg     AL.checkAtMostNumArgs(S, 1);
72637330f729Sjoerg   else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) &&
72647330f729Sjoerg            !S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
72657330f729Sjoerg     return;
72667330f729Sjoerg 
72677330f729Sjoerg   if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope())
72687330f729Sjoerg     S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL;
72697330f729Sjoerg 
72707330f729Sjoerg   D->addAttr(::new (S.Context) DeprecatedAttr(S.Context, AL, Str, Replacement));
72717330f729Sjoerg }
72727330f729Sjoerg 
isGlobalVar(const Decl * D)72737330f729Sjoerg static bool isGlobalVar(const Decl *D) {
72747330f729Sjoerg   if (const auto *S = dyn_cast<VarDecl>(D))
72757330f729Sjoerg     return S->hasGlobalStorage();
72767330f729Sjoerg   return false;
72777330f729Sjoerg }
72787330f729Sjoerg 
handleNoSanitizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)72797330f729Sjoerg static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7280*e038c9c4Sjoerg   if (!AL.checkAtLeastNumArgs(S, 1))
72817330f729Sjoerg     return;
72827330f729Sjoerg 
72837330f729Sjoerg   std::vector<StringRef> Sanitizers;
72847330f729Sjoerg 
72857330f729Sjoerg   for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
72867330f729Sjoerg     StringRef SanitizerName;
72877330f729Sjoerg     SourceLocation LiteralLoc;
72887330f729Sjoerg 
72897330f729Sjoerg     if (!S.checkStringLiteralArgumentAttr(AL, I, SanitizerName, &LiteralLoc))
72907330f729Sjoerg       return;
72917330f729Sjoerg 
72927330f729Sjoerg     if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) ==
72937330f729Sjoerg         SanitizerMask())
72947330f729Sjoerg       S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
72957330f729Sjoerg     else if (isGlobalVar(D) && SanitizerName != "address")
72967330f729Sjoerg       S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
72977330f729Sjoerg           << AL << ExpectedFunctionOrMethod;
72987330f729Sjoerg     Sanitizers.push_back(SanitizerName);
72997330f729Sjoerg   }
73007330f729Sjoerg 
73017330f729Sjoerg   D->addAttr(::new (S.Context) NoSanitizeAttr(S.Context, AL, Sanitizers.data(),
73027330f729Sjoerg                                               Sanitizers.size()));
73037330f729Sjoerg }
73047330f729Sjoerg 
handleNoSanitizeSpecificAttr(Sema & S,Decl * D,const ParsedAttr & AL)73057330f729Sjoerg static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
73067330f729Sjoerg                                          const ParsedAttr &AL) {
73077330f729Sjoerg   StringRef AttrName = AL.getAttrName()->getName();
73087330f729Sjoerg   normalizeName(AttrName);
73097330f729Sjoerg   StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName)
73107330f729Sjoerg                                 .Case("no_address_safety_analysis", "address")
73117330f729Sjoerg                                 .Case("no_sanitize_address", "address")
73127330f729Sjoerg                                 .Case("no_sanitize_thread", "thread")
73137330f729Sjoerg                                 .Case("no_sanitize_memory", "memory");
73147330f729Sjoerg   if (isGlobalVar(D) && SanitizerName != "address")
73157330f729Sjoerg     S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
73167330f729Sjoerg         << AL << ExpectedFunction;
73177330f729Sjoerg 
73187330f729Sjoerg   // FIXME: Rather than create a NoSanitizeSpecificAttr, this creates a
73197330f729Sjoerg   // NoSanitizeAttr object; but we need to calculate the correct spelling list
73207330f729Sjoerg   // index rather than incorrectly assume the index for NoSanitizeSpecificAttr
73217330f729Sjoerg   // has the same spellings as the index for NoSanitizeAttr. We don't have a
73227330f729Sjoerg   // general way to "translate" between the two, so this hack attempts to work
73237330f729Sjoerg   // around the issue with hard-coded indicies. This is critical for calling
73247330f729Sjoerg   // getSpelling() or prettyPrint() on the resulting semantic attribute object
73257330f729Sjoerg   // without failing assertions.
73267330f729Sjoerg   unsigned TranslatedSpellingIndex = 0;
73277330f729Sjoerg   if (AL.isC2xAttribute() || AL.isCXX11Attribute())
73287330f729Sjoerg     TranslatedSpellingIndex = 1;
73297330f729Sjoerg 
73307330f729Sjoerg   AttributeCommonInfo Info = AL;
73317330f729Sjoerg   Info.setAttributeSpellingListIndex(TranslatedSpellingIndex);
73327330f729Sjoerg   D->addAttr(::new (S.Context)
73337330f729Sjoerg                  NoSanitizeAttr(S.Context, Info, &SanitizerName, 1));
73347330f729Sjoerg }
73357330f729Sjoerg 
handleInternalLinkageAttr(Sema & S,Decl * D,const ParsedAttr & AL)73367330f729Sjoerg static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
73377330f729Sjoerg   if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr(D, AL))
73387330f729Sjoerg     D->addAttr(Internal);
73397330f729Sjoerg }
73407330f729Sjoerg 
handleOpenCLNoSVMAttr(Sema & S,Decl * D,const ParsedAttr & AL)73417330f729Sjoerg static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
73427330f729Sjoerg   if (S.LangOpts.OpenCLVersion != 200)
73437330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
73447330f729Sjoerg         << AL << "2.0" << 0;
73457330f729Sjoerg   else
73467330f729Sjoerg     S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored) << AL
73477330f729Sjoerg                                                                    << "2.0";
73487330f729Sjoerg }
73497330f729Sjoerg 
handleOpenCLAccessAttr(Sema & S,Decl * D,const ParsedAttr & AL)73507330f729Sjoerg static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
73517330f729Sjoerg   if (D->isInvalidDecl())
73527330f729Sjoerg     return;
73537330f729Sjoerg 
73547330f729Sjoerg   // Check if there is only one access qualifier.
73557330f729Sjoerg   if (D->hasAttr<OpenCLAccessAttr>()) {
73567330f729Sjoerg     if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() ==
73577330f729Sjoerg         AL.getSemanticSpelling()) {
73587330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_duplicate_declspec)
73597330f729Sjoerg           << AL.getAttrName()->getName() << AL.getRange();
73607330f729Sjoerg     } else {
73617330f729Sjoerg       S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
73627330f729Sjoerg           << D->getSourceRange();
73637330f729Sjoerg       D->setInvalidDecl(true);
73647330f729Sjoerg       return;
73657330f729Sjoerg     }
73667330f729Sjoerg   }
73677330f729Sjoerg 
73687330f729Sjoerg   // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an
73697330f729Sjoerg   // image object can be read and written.
73707330f729Sjoerg   // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe
73717330f729Sjoerg   // object. Using the read_write (or __read_write) qualifier with the pipe
73727330f729Sjoerg   // qualifier is a compilation error.
73737330f729Sjoerg   if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
73747330f729Sjoerg     const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
73757330f729Sjoerg     if (AL.getAttrName()->getName().find("read_write") != StringRef::npos) {
73767330f729Sjoerg       if ((!S.getLangOpts().OpenCLCPlusPlus &&
73777330f729Sjoerg            S.getLangOpts().OpenCLVersion < 200) ||
73787330f729Sjoerg           DeclTy->isPipeType()) {
73797330f729Sjoerg         S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
73807330f729Sjoerg             << AL << PDecl->getType() << DeclTy->isImageType();
73817330f729Sjoerg         D->setInvalidDecl(true);
73827330f729Sjoerg         return;
73837330f729Sjoerg       }
73847330f729Sjoerg     }
73857330f729Sjoerg   }
73867330f729Sjoerg 
73877330f729Sjoerg   D->addAttr(::new (S.Context) OpenCLAccessAttr(S.Context, AL));
73887330f729Sjoerg }
73897330f729Sjoerg 
handleSYCLKernelAttr(Sema & S,Decl * D,const ParsedAttr & AL)7390*e038c9c4Sjoerg static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7391*e038c9c4Sjoerg   // The 'sycl_kernel' attribute applies only to function templates.
7392*e038c9c4Sjoerg   const auto *FD = cast<FunctionDecl>(D);
7393*e038c9c4Sjoerg   const FunctionTemplateDecl *FT = FD->getDescribedFunctionTemplate();
7394*e038c9c4Sjoerg   assert(FT && "Function template is expected");
7395*e038c9c4Sjoerg 
7396*e038c9c4Sjoerg   // Function template must have at least two template parameters.
7397*e038c9c4Sjoerg   const TemplateParameterList *TL = FT->getTemplateParameters();
7398*e038c9c4Sjoerg   if (TL->size() < 2) {
7399*e038c9c4Sjoerg     S.Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_template_params);
7400*e038c9c4Sjoerg     return;
7401*e038c9c4Sjoerg   }
7402*e038c9c4Sjoerg 
7403*e038c9c4Sjoerg   // Template parameters must be typenames.
7404*e038c9c4Sjoerg   for (unsigned I = 0; I < 2; ++I) {
7405*e038c9c4Sjoerg     const NamedDecl *TParam = TL->getParam(I);
7406*e038c9c4Sjoerg     if (isa<NonTypeTemplateParmDecl>(TParam)) {
7407*e038c9c4Sjoerg       S.Diag(FT->getLocation(),
7408*e038c9c4Sjoerg              diag::warn_sycl_kernel_invalid_template_param_type);
7409*e038c9c4Sjoerg       return;
7410*e038c9c4Sjoerg     }
7411*e038c9c4Sjoerg   }
7412*e038c9c4Sjoerg 
7413*e038c9c4Sjoerg   // Function must have at least one argument.
7414*e038c9c4Sjoerg   if (getFunctionOrMethodNumParams(D) != 1) {
7415*e038c9c4Sjoerg     S.Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_function_params);
7416*e038c9c4Sjoerg     return;
7417*e038c9c4Sjoerg   }
7418*e038c9c4Sjoerg 
7419*e038c9c4Sjoerg   // Function must return void.
7420*e038c9c4Sjoerg   QualType RetTy = getFunctionOrMethodResultType(D);
7421*e038c9c4Sjoerg   if (!RetTy->isVoidType()) {
7422*e038c9c4Sjoerg     S.Diag(FT->getLocation(), diag::warn_sycl_kernel_return_type);
7423*e038c9c4Sjoerg     return;
7424*e038c9c4Sjoerg   }
7425*e038c9c4Sjoerg 
7426*e038c9c4Sjoerg   handleSimpleAttribute<SYCLKernelAttr>(S, D, AL);
7427*e038c9c4Sjoerg }
7428*e038c9c4Sjoerg 
handleDestroyAttr(Sema & S,Decl * D,const ParsedAttr & A)74297330f729Sjoerg static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) {
74307330f729Sjoerg   if (!cast<VarDecl>(D)->hasGlobalStorage()) {
74317330f729Sjoerg     S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var)
74327330f729Sjoerg         << (A.getKind() == ParsedAttr::AT_AlwaysDestroy);
74337330f729Sjoerg     return;
74347330f729Sjoerg   }
74357330f729Sjoerg 
74367330f729Sjoerg   if (A.getKind() == ParsedAttr::AT_AlwaysDestroy)
7437*e038c9c4Sjoerg     handleSimpleAttribute<AlwaysDestroyAttr>(S, D, A);
74387330f729Sjoerg   else
7439*e038c9c4Sjoerg     handleSimpleAttribute<NoDestroyAttr>(S, D, A);
74407330f729Sjoerg }
74417330f729Sjoerg 
handleUninitializedAttr(Sema & S,Decl * D,const ParsedAttr & AL)74427330f729Sjoerg static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
74437330f729Sjoerg   assert(cast<VarDecl>(D)->getStorageDuration() == SD_Automatic &&
74447330f729Sjoerg          "uninitialized is only valid on automatic duration variables");
74457330f729Sjoerg   D->addAttr(::new (S.Context) UninitializedAttr(S.Context, AL));
74467330f729Sjoerg }
74477330f729Sjoerg 
tryMakeVariablePseudoStrong(Sema & S,VarDecl * VD,bool DiagnoseFailure)74487330f729Sjoerg static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD,
74497330f729Sjoerg                                         bool DiagnoseFailure) {
74507330f729Sjoerg   QualType Ty = VD->getType();
74517330f729Sjoerg   if (!Ty->isObjCRetainableType()) {
74527330f729Sjoerg     if (DiagnoseFailure) {
74537330f729Sjoerg       S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
74547330f729Sjoerg           << 0;
74557330f729Sjoerg     }
74567330f729Sjoerg     return false;
74577330f729Sjoerg   }
74587330f729Sjoerg 
74597330f729Sjoerg   Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime();
74607330f729Sjoerg 
74617330f729Sjoerg   // Sema::inferObjCARCLifetime must run after processing decl attributes
74627330f729Sjoerg   // (because __block lowers to an attribute), so if the lifetime hasn't been
74637330f729Sjoerg   // explicitly specified, infer it locally now.
74647330f729Sjoerg   if (LifetimeQual == Qualifiers::OCL_None)
74657330f729Sjoerg     LifetimeQual = Ty->getObjCARCImplicitLifetime();
74667330f729Sjoerg 
74677330f729Sjoerg   // The attributes only really makes sense for __strong variables; ignore any
74687330f729Sjoerg   // attempts to annotate a parameter with any other lifetime qualifier.
74697330f729Sjoerg   if (LifetimeQual != Qualifiers::OCL_Strong) {
74707330f729Sjoerg     if (DiagnoseFailure) {
74717330f729Sjoerg       S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
74727330f729Sjoerg           << 1;
74737330f729Sjoerg     }
74747330f729Sjoerg     return false;
74757330f729Sjoerg   }
74767330f729Sjoerg 
74777330f729Sjoerg   // Tampering with the type of a VarDecl here is a bit of a hack, but we need
74787330f729Sjoerg   // to ensure that the variable is 'const' so that we can error on
74797330f729Sjoerg   // modification, which can otherwise over-release.
74807330f729Sjoerg   VD->setType(Ty.withConst());
74817330f729Sjoerg   VD->setARCPseudoStrong(true);
74827330f729Sjoerg   return true;
74837330f729Sjoerg }
74847330f729Sjoerg 
handleObjCExternallyRetainedAttr(Sema & S,Decl * D,const ParsedAttr & AL)74857330f729Sjoerg static void handleObjCExternallyRetainedAttr(Sema &S, Decl *D,
74867330f729Sjoerg                                              const ParsedAttr &AL) {
74877330f729Sjoerg   if (auto *VD = dyn_cast<VarDecl>(D)) {
74887330f729Sjoerg     assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically");
74897330f729Sjoerg     if (!VD->hasLocalStorage()) {
74907330f729Sjoerg       S.Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
74917330f729Sjoerg           << 0;
74927330f729Sjoerg       return;
74937330f729Sjoerg     }
74947330f729Sjoerg 
74957330f729Sjoerg     if (!tryMakeVariablePseudoStrong(S, VD, /*DiagnoseFailure=*/true))
74967330f729Sjoerg       return;
74977330f729Sjoerg 
74987330f729Sjoerg     handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
74997330f729Sjoerg     return;
75007330f729Sjoerg   }
75017330f729Sjoerg 
75027330f729Sjoerg   // If D is a function-like declaration (method, block, or function), then we
75037330f729Sjoerg   // make every parameter psuedo-strong.
7504*e038c9c4Sjoerg   unsigned NumParams =
7505*e038c9c4Sjoerg       hasFunctionProto(D) ? getFunctionOrMethodNumParams(D) : 0;
7506*e038c9c4Sjoerg   for (unsigned I = 0; I != NumParams; ++I) {
75077330f729Sjoerg     auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I));
75087330f729Sjoerg     QualType Ty = PVD->getType();
75097330f729Sjoerg 
75107330f729Sjoerg     // If a user wrote a parameter with __strong explicitly, then assume they
75117330f729Sjoerg     // want "real" strong semantics for that parameter. This works because if
75127330f729Sjoerg     // the parameter was written with __strong, then the strong qualifier will
75137330f729Sjoerg     // be non-local.
75147330f729Sjoerg     if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() ==
75157330f729Sjoerg         Qualifiers::OCL_Strong)
75167330f729Sjoerg       continue;
75177330f729Sjoerg 
75187330f729Sjoerg     tryMakeVariablePseudoStrong(S, PVD, /*DiagnoseFailure=*/false);
75197330f729Sjoerg   }
75207330f729Sjoerg   handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
75217330f729Sjoerg }
75227330f729Sjoerg 
handleMIGServerRoutineAttr(Sema & S,Decl * D,const ParsedAttr & AL)75237330f729Sjoerg static void handleMIGServerRoutineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
75247330f729Sjoerg   // Check that the return type is a `typedef int kern_return_t` or a typedef
75257330f729Sjoerg   // around it, because otherwise MIG convention checks make no sense.
75267330f729Sjoerg   // BlockDecl doesn't store a return type, so it's annoying to check,
75277330f729Sjoerg   // so let's skip it for now.
75287330f729Sjoerg   if (!isa<BlockDecl>(D)) {
75297330f729Sjoerg     QualType T = getFunctionOrMethodResultType(D);
75307330f729Sjoerg     bool IsKernReturnT = false;
75317330f729Sjoerg     while (const auto *TT = T->getAs<TypedefType>()) {
75327330f729Sjoerg       IsKernReturnT = (TT->getDecl()->getName() == "kern_return_t");
75337330f729Sjoerg       T = TT->desugar();
75347330f729Sjoerg     }
75357330f729Sjoerg     if (!IsKernReturnT || T.getCanonicalType() != S.getASTContext().IntTy) {
75367330f729Sjoerg       S.Diag(D->getBeginLoc(),
75377330f729Sjoerg              diag::warn_mig_server_routine_does_not_return_kern_return_t);
75387330f729Sjoerg       return;
75397330f729Sjoerg     }
75407330f729Sjoerg   }
75417330f729Sjoerg 
75427330f729Sjoerg   handleSimpleAttribute<MIGServerRoutineAttr>(S, D, AL);
75437330f729Sjoerg }
75447330f729Sjoerg 
handleMSAllocatorAttr(Sema & S,Decl * D,const ParsedAttr & AL)75457330f729Sjoerg static void handleMSAllocatorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
75467330f729Sjoerg   // Warn if the return type is not a pointer or reference type.
75477330f729Sjoerg   if (auto *FD = dyn_cast<FunctionDecl>(D)) {
75487330f729Sjoerg     QualType RetTy = FD->getReturnType();
75497330f729Sjoerg     if (!RetTy->isPointerType() && !RetTy->isReferenceType()) {
75507330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_declspec_allocator_nonpointer)
75517330f729Sjoerg           << AL.getRange() << RetTy;
75527330f729Sjoerg       return;
75537330f729Sjoerg     }
75547330f729Sjoerg   }
75557330f729Sjoerg 
75567330f729Sjoerg   handleSimpleAttribute<MSAllocatorAttr>(S, D, AL);
75577330f729Sjoerg }
75587330f729Sjoerg 
handleAcquireHandleAttr(Sema & S,Decl * D,const ParsedAttr & AL)7559*e038c9c4Sjoerg static void handleAcquireHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7560*e038c9c4Sjoerg   if (AL.isUsedAsTypeAttr())
7561*e038c9c4Sjoerg     return;
7562*e038c9c4Sjoerg   // Warn if the parameter is definitely not an output parameter.
7563*e038c9c4Sjoerg   if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
7564*e038c9c4Sjoerg     if (PVD->getType()->isIntegerType()) {
7565*e038c9c4Sjoerg       S.Diag(AL.getLoc(), diag::err_attribute_output_parameter)
7566*e038c9c4Sjoerg           << AL.getRange();
7567*e038c9c4Sjoerg       return;
7568*e038c9c4Sjoerg     }
7569*e038c9c4Sjoerg   }
7570*e038c9c4Sjoerg   StringRef Argument;
7571*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument))
7572*e038c9c4Sjoerg     return;
7573*e038c9c4Sjoerg   D->addAttr(AcquireHandleAttr::Create(S.Context, Argument, AL));
7574*e038c9c4Sjoerg }
7575*e038c9c4Sjoerg 
7576*e038c9c4Sjoerg template<typename Attr>
handleHandleAttr(Sema & S,Decl * D,const ParsedAttr & AL)7577*e038c9c4Sjoerg static void handleHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7578*e038c9c4Sjoerg   StringRef Argument;
7579*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument))
7580*e038c9c4Sjoerg     return;
7581*e038c9c4Sjoerg   D->addAttr(Attr::Create(S.Context, Argument, AL));
7582*e038c9c4Sjoerg }
7583*e038c9c4Sjoerg 
handleCFGuardAttr(Sema & S,Decl * D,const ParsedAttr & AL)7584*e038c9c4Sjoerg static void handleCFGuardAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7585*e038c9c4Sjoerg   // The guard attribute takes a single identifier argument.
7586*e038c9c4Sjoerg 
7587*e038c9c4Sjoerg   if (!AL.isArgIdent(0)) {
7588*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
7589*e038c9c4Sjoerg         << AL << AANT_ArgumentIdentifier;
7590*e038c9c4Sjoerg     return;
7591*e038c9c4Sjoerg   }
7592*e038c9c4Sjoerg 
7593*e038c9c4Sjoerg   CFGuardAttr::GuardArg Arg;
7594*e038c9c4Sjoerg   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
7595*e038c9c4Sjoerg   if (!CFGuardAttr::ConvertStrToGuardArg(II->getName(), Arg)) {
7596*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
7597*e038c9c4Sjoerg     return;
7598*e038c9c4Sjoerg   }
7599*e038c9c4Sjoerg 
7600*e038c9c4Sjoerg   D->addAttr(::new (S.Context) CFGuardAttr(S.Context, AL, Arg));
7601*e038c9c4Sjoerg }
7602*e038c9c4Sjoerg 
7603*e038c9c4Sjoerg 
7604*e038c9c4Sjoerg template <typename AttrTy>
findEnforceTCBAttrByName(Decl * D,StringRef Name)7605*e038c9c4Sjoerg static const AttrTy *findEnforceTCBAttrByName(Decl *D, StringRef Name) {
7606*e038c9c4Sjoerg   auto Attrs = D->specific_attrs<AttrTy>();
7607*e038c9c4Sjoerg   auto I = llvm::find_if(Attrs,
7608*e038c9c4Sjoerg                          [Name](const AttrTy *A) {
7609*e038c9c4Sjoerg                            return A->getTCBName() == Name;
7610*e038c9c4Sjoerg                          });
7611*e038c9c4Sjoerg   return I == Attrs.end() ? nullptr : *I;
7612*e038c9c4Sjoerg }
7613*e038c9c4Sjoerg 
7614*e038c9c4Sjoerg template <typename AttrTy, typename ConflictingAttrTy>
handleEnforceTCBAttr(Sema & S,Decl * D,const ParsedAttr & AL)7615*e038c9c4Sjoerg static void handleEnforceTCBAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7616*e038c9c4Sjoerg   StringRef Argument;
7617*e038c9c4Sjoerg   if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument))
7618*e038c9c4Sjoerg     return;
7619*e038c9c4Sjoerg 
7620*e038c9c4Sjoerg   // A function cannot be have both regular and leaf membership in the same TCB.
7621*e038c9c4Sjoerg   if (const ConflictingAttrTy *ConflictingAttr =
7622*e038c9c4Sjoerg       findEnforceTCBAttrByName<ConflictingAttrTy>(D, Argument)) {
7623*e038c9c4Sjoerg     // We could attach a note to the other attribute but in this case
7624*e038c9c4Sjoerg     // there's no need given how the two are very close to each other.
7625*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::err_tcb_conflicting_attributes)
7626*e038c9c4Sjoerg       << AL.getAttrName()->getName() << ConflictingAttr->getAttrName()->getName()
7627*e038c9c4Sjoerg       << Argument;
7628*e038c9c4Sjoerg 
7629*e038c9c4Sjoerg     // Error recovery: drop the non-leaf attribute so that to suppress
7630*e038c9c4Sjoerg     // all future warnings caused by erroneous attributes. The leaf attribute
7631*e038c9c4Sjoerg     // needs to be kept because it can only suppresses warnings, not cause them.
7632*e038c9c4Sjoerg     D->dropAttr<EnforceTCBAttr>();
7633*e038c9c4Sjoerg     return;
7634*e038c9c4Sjoerg   }
7635*e038c9c4Sjoerg 
7636*e038c9c4Sjoerg   D->addAttr(AttrTy::Create(S.Context, Argument, AL));
7637*e038c9c4Sjoerg }
7638*e038c9c4Sjoerg 
7639*e038c9c4Sjoerg template <typename AttrTy, typename ConflictingAttrTy>
mergeEnforceTCBAttrImpl(Sema & S,Decl * D,const AttrTy & AL)7640*e038c9c4Sjoerg static AttrTy *mergeEnforceTCBAttrImpl(Sema &S, Decl *D, const AttrTy &AL) {
7641*e038c9c4Sjoerg   // Check if the new redeclaration has different leaf-ness in the same TCB.
7642*e038c9c4Sjoerg   StringRef TCBName = AL.getTCBName();
7643*e038c9c4Sjoerg   if (const ConflictingAttrTy *ConflictingAttr =
7644*e038c9c4Sjoerg       findEnforceTCBAttrByName<ConflictingAttrTy>(D, TCBName)) {
7645*e038c9c4Sjoerg     S.Diag(ConflictingAttr->getLoc(), diag::err_tcb_conflicting_attributes)
7646*e038c9c4Sjoerg       << ConflictingAttr->getAttrName()->getName()
7647*e038c9c4Sjoerg       << AL.getAttrName()->getName() << TCBName;
7648*e038c9c4Sjoerg 
7649*e038c9c4Sjoerg     // Add a note so that the user could easily find the conflicting attribute.
7650*e038c9c4Sjoerg     S.Diag(AL.getLoc(), diag::note_conflicting_attribute);
7651*e038c9c4Sjoerg 
7652*e038c9c4Sjoerg     // More error recovery.
7653*e038c9c4Sjoerg     D->dropAttr<EnforceTCBAttr>();
7654*e038c9c4Sjoerg     return nullptr;
7655*e038c9c4Sjoerg   }
7656*e038c9c4Sjoerg 
7657*e038c9c4Sjoerg   ASTContext &Context = S.getASTContext();
7658*e038c9c4Sjoerg   return ::new(Context) AttrTy(Context, AL, AL.getTCBName());
7659*e038c9c4Sjoerg }
7660*e038c9c4Sjoerg 
mergeEnforceTCBAttr(Decl * D,const EnforceTCBAttr & AL)7661*e038c9c4Sjoerg EnforceTCBAttr *Sema::mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL) {
7662*e038c9c4Sjoerg   return mergeEnforceTCBAttrImpl<EnforceTCBAttr, EnforceTCBLeafAttr>(
7663*e038c9c4Sjoerg       *this, D, AL);
7664*e038c9c4Sjoerg }
7665*e038c9c4Sjoerg 
mergeEnforceTCBLeafAttr(Decl * D,const EnforceTCBLeafAttr & AL)7666*e038c9c4Sjoerg EnforceTCBLeafAttr *Sema::mergeEnforceTCBLeafAttr(
7667*e038c9c4Sjoerg     Decl *D, const EnforceTCBLeafAttr &AL) {
7668*e038c9c4Sjoerg   return mergeEnforceTCBAttrImpl<EnforceTCBLeafAttr, EnforceTCBAttr>(
7669*e038c9c4Sjoerg       *this, D, AL);
7670*e038c9c4Sjoerg }
7671*e038c9c4Sjoerg 
76727330f729Sjoerg //===----------------------------------------------------------------------===//
76737330f729Sjoerg // Top Level Sema Entry Points
76747330f729Sjoerg //===----------------------------------------------------------------------===//
76757330f729Sjoerg 
76767330f729Sjoerg /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
76777330f729Sjoerg /// the attribute applies to decls.  If the attribute is a type attribute, just
76787330f729Sjoerg /// silently ignore it if a GNU attribute.
ProcessDeclAttribute(Sema & S,Scope * scope,Decl * D,const ParsedAttr & AL,bool IncludeCXX11Attributes)76797330f729Sjoerg static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
76807330f729Sjoerg                                  const ParsedAttr &AL,
76817330f729Sjoerg                                  bool IncludeCXX11Attributes) {
76827330f729Sjoerg   if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
76837330f729Sjoerg     return;
76847330f729Sjoerg 
76857330f729Sjoerg   // Ignore C++11 attributes on declarator chunks: they appertain to the type
76867330f729Sjoerg   // instead.
76877330f729Sjoerg   if (AL.isCXX11Attribute() && !IncludeCXX11Attributes)
76887330f729Sjoerg     return;
76897330f729Sjoerg 
76907330f729Sjoerg   // Unknown attributes are automatically warned on. Target-specific attributes
76917330f729Sjoerg   // which do not apply to the current target architecture are treated as
76927330f729Sjoerg   // though they were unknown attributes.
76937330f729Sjoerg   if (AL.getKind() == ParsedAttr::UnknownAttribute ||
76947330f729Sjoerg       !AL.existsInTarget(S.Context.getTargetInfo())) {
76957330f729Sjoerg     S.Diag(AL.getLoc(),
76967330f729Sjoerg            AL.isDeclspecAttribute()
76977330f729Sjoerg                ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
76987330f729Sjoerg                : (unsigned)diag::warn_unknown_attribute_ignored)
7699*e038c9c4Sjoerg         << AL << AL.getRange();
77007330f729Sjoerg     return;
77017330f729Sjoerg   }
77027330f729Sjoerg 
7703*e038c9c4Sjoerg   if (S.checkCommonAttributeFeatures(D, AL))
77047330f729Sjoerg     return;
77057330f729Sjoerg 
77067330f729Sjoerg   switch (AL.getKind()) {
77077330f729Sjoerg   default:
7708*e038c9c4Sjoerg     if (AL.getInfo().handleDeclAttribute(S, D, AL) != ParsedAttrInfo::NotHandled)
7709*e038c9c4Sjoerg       break;
77107330f729Sjoerg     if (!AL.isStmtAttr()) {
77117330f729Sjoerg       // Type attributes are handled elsewhere; silently move on.
77127330f729Sjoerg       assert(AL.isTypeAttr() && "Non-type attribute not handled");
77137330f729Sjoerg       break;
77147330f729Sjoerg     }
7715*e038c9c4Sjoerg     // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
7716*e038c9c4Sjoerg     // statement attribute is not written on a declaration, but this code is
7717*e038c9c4Sjoerg     // needed for attributes in Attr.td that do not list any subjects.
77187330f729Sjoerg     S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
77197330f729Sjoerg         << AL << D->getLocation();
77207330f729Sjoerg     break;
77217330f729Sjoerg   case ParsedAttr::AT_Interrupt:
77227330f729Sjoerg     handleInterruptAttr(S, D, AL);
77237330f729Sjoerg     break;
77247330f729Sjoerg   case ParsedAttr::AT_X86ForceAlignArgPointer:
77257330f729Sjoerg     handleX86ForceAlignArgPointerAttr(S, D, AL);
77267330f729Sjoerg     break;
77277330f729Sjoerg   case ParsedAttr::AT_DLLExport:
77287330f729Sjoerg   case ParsedAttr::AT_DLLImport:
77297330f729Sjoerg     handleDLLAttr(S, D, AL);
77307330f729Sjoerg     break;
77317330f729Sjoerg   case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
77327330f729Sjoerg     handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL);
77337330f729Sjoerg     break;
77347330f729Sjoerg   case ParsedAttr::AT_AMDGPUWavesPerEU:
77357330f729Sjoerg     handleAMDGPUWavesPerEUAttr(S, D, AL);
77367330f729Sjoerg     break;
77377330f729Sjoerg   case ParsedAttr::AT_AMDGPUNumSGPR:
77387330f729Sjoerg     handleAMDGPUNumSGPRAttr(S, D, AL);
77397330f729Sjoerg     break;
77407330f729Sjoerg   case ParsedAttr::AT_AMDGPUNumVGPR:
77417330f729Sjoerg     handleAMDGPUNumVGPRAttr(S, D, AL);
77427330f729Sjoerg     break;
77437330f729Sjoerg   case ParsedAttr::AT_AVRSignal:
77447330f729Sjoerg     handleAVRSignalAttr(S, D, AL);
77457330f729Sjoerg     break;
7746*e038c9c4Sjoerg   case ParsedAttr::AT_BPFPreserveAccessIndex:
7747*e038c9c4Sjoerg     handleBPFPreserveAccessIndexAttr(S, D, AL);
7748*e038c9c4Sjoerg     break;
7749*e038c9c4Sjoerg   case ParsedAttr::AT_WebAssemblyExportName:
7750*e038c9c4Sjoerg     handleWebAssemblyExportNameAttr(S, D, AL);
7751*e038c9c4Sjoerg     break;
77527330f729Sjoerg   case ParsedAttr::AT_WebAssemblyImportModule:
77537330f729Sjoerg     handleWebAssemblyImportModuleAttr(S, D, AL);
77547330f729Sjoerg     break;
77557330f729Sjoerg   case ParsedAttr::AT_WebAssemblyImportName:
77567330f729Sjoerg     handleWebAssemblyImportNameAttr(S, D, AL);
77577330f729Sjoerg     break;
77587330f729Sjoerg   case ParsedAttr::AT_IBOutlet:
77597330f729Sjoerg     handleIBOutlet(S, D, AL);
77607330f729Sjoerg     break;
77617330f729Sjoerg   case ParsedAttr::AT_IBOutletCollection:
77627330f729Sjoerg     handleIBOutletCollection(S, D, AL);
77637330f729Sjoerg     break;
77647330f729Sjoerg   case ParsedAttr::AT_IFunc:
77657330f729Sjoerg     handleIFuncAttr(S, D, AL);
77667330f729Sjoerg     break;
77677330f729Sjoerg   case ParsedAttr::AT_Alias:
77687330f729Sjoerg     handleAliasAttr(S, D, AL);
77697330f729Sjoerg     break;
77707330f729Sjoerg   case ParsedAttr::AT_Aligned:
77717330f729Sjoerg     handleAlignedAttr(S, D, AL);
77727330f729Sjoerg     break;
77737330f729Sjoerg   case ParsedAttr::AT_AlignValue:
77747330f729Sjoerg     handleAlignValueAttr(S, D, AL);
77757330f729Sjoerg     break;
77767330f729Sjoerg   case ParsedAttr::AT_AllocSize:
77777330f729Sjoerg     handleAllocSizeAttr(S, D, AL);
77787330f729Sjoerg     break;
77797330f729Sjoerg   case ParsedAttr::AT_AlwaysInline:
77807330f729Sjoerg     handleAlwaysInlineAttr(S, D, AL);
77817330f729Sjoerg     break;
77827330f729Sjoerg   case ParsedAttr::AT_AnalyzerNoReturn:
77837330f729Sjoerg     handleAnalyzerNoReturnAttr(S, D, AL);
77847330f729Sjoerg     break;
77857330f729Sjoerg   case ParsedAttr::AT_TLSModel:
77867330f729Sjoerg     handleTLSModelAttr(S, D, AL);
77877330f729Sjoerg     break;
77887330f729Sjoerg   case ParsedAttr::AT_Annotate:
77897330f729Sjoerg     handleAnnotateAttr(S, D, AL);
77907330f729Sjoerg     break;
77917330f729Sjoerg   case ParsedAttr::AT_Availability:
77927330f729Sjoerg     handleAvailabilityAttr(S, D, AL);
77937330f729Sjoerg     break;
77947330f729Sjoerg   case ParsedAttr::AT_CarriesDependency:
77957330f729Sjoerg     handleDependencyAttr(S, scope, D, AL);
77967330f729Sjoerg     break;
77977330f729Sjoerg   case ParsedAttr::AT_CPUDispatch:
77987330f729Sjoerg   case ParsedAttr::AT_CPUSpecific:
77997330f729Sjoerg     handleCPUSpecificAttr(S, D, AL);
78007330f729Sjoerg     break;
78017330f729Sjoerg   case ParsedAttr::AT_Common:
78027330f729Sjoerg     handleCommonAttr(S, D, AL);
78037330f729Sjoerg     break;
78047330f729Sjoerg   case ParsedAttr::AT_CUDAConstant:
78057330f729Sjoerg     handleConstantAttr(S, D, AL);
78067330f729Sjoerg     break;
78077330f729Sjoerg   case ParsedAttr::AT_PassObjectSize:
78087330f729Sjoerg     handlePassObjectSizeAttr(S, D, AL);
78097330f729Sjoerg     break;
78107330f729Sjoerg   case ParsedAttr::AT_Constructor:
78117330f729Sjoerg       handleConstructorAttr(S, D, AL);
78127330f729Sjoerg     break;
78137330f729Sjoerg   case ParsedAttr::AT_Deprecated:
78147330f729Sjoerg     handleDeprecatedAttr(S, D, AL);
78157330f729Sjoerg     break;
78167330f729Sjoerg   case ParsedAttr::AT_Destructor:
78177330f729Sjoerg       handleDestructorAttr(S, D, AL);
78187330f729Sjoerg     break;
78197330f729Sjoerg   case ParsedAttr::AT_EnableIf:
78207330f729Sjoerg     handleEnableIfAttr(S, D, AL);
78217330f729Sjoerg     break;
78227330f729Sjoerg   case ParsedAttr::AT_DiagnoseIf:
78237330f729Sjoerg     handleDiagnoseIfAttr(S, D, AL);
78247330f729Sjoerg     break;
7825*e038c9c4Sjoerg   case ParsedAttr::AT_NoBuiltin:
7826*e038c9c4Sjoerg     handleNoBuiltinAttr(S, D, AL);
7827*e038c9c4Sjoerg     break;
78287330f729Sjoerg   case ParsedAttr::AT_ExtVectorType:
78297330f729Sjoerg     handleExtVectorTypeAttr(S, D, AL);
78307330f729Sjoerg     break;
78317330f729Sjoerg   case ParsedAttr::AT_ExternalSourceSymbol:
78327330f729Sjoerg     handleExternalSourceSymbolAttr(S, D, AL);
78337330f729Sjoerg     break;
78347330f729Sjoerg   case ParsedAttr::AT_MinSize:
78357330f729Sjoerg     handleMinSizeAttr(S, D, AL);
78367330f729Sjoerg     break;
78377330f729Sjoerg   case ParsedAttr::AT_OptimizeNone:
78387330f729Sjoerg     handleOptimizeNoneAttr(S, D, AL);
78397330f729Sjoerg     break;
78407330f729Sjoerg   case ParsedAttr::AT_EnumExtensibility:
78417330f729Sjoerg     handleEnumExtensibilityAttr(S, D, AL);
78427330f729Sjoerg     break;
7843*e038c9c4Sjoerg   case ParsedAttr::AT_SYCLKernel:
7844*e038c9c4Sjoerg     handleSYCLKernelAttr(S, D, AL);
78457330f729Sjoerg     break;
78467330f729Sjoerg   case ParsedAttr::AT_Format:
78477330f729Sjoerg     handleFormatAttr(S, D, AL);
78487330f729Sjoerg     break;
78497330f729Sjoerg   case ParsedAttr::AT_FormatArg:
78507330f729Sjoerg     handleFormatArgAttr(S, D, AL);
78517330f729Sjoerg     break;
78527330f729Sjoerg   case ParsedAttr::AT_Callback:
78537330f729Sjoerg     handleCallbackAttr(S, D, AL);
78547330f729Sjoerg     break;
7855*e038c9c4Sjoerg   case ParsedAttr::AT_CalledOnce:
7856*e038c9c4Sjoerg     handleCalledOnceAttr(S, D, AL);
7857*e038c9c4Sjoerg     break;
78587330f729Sjoerg   case ParsedAttr::AT_CUDAGlobal:
78597330f729Sjoerg     handleGlobalAttr(S, D, AL);
78607330f729Sjoerg     break;
78617330f729Sjoerg   case ParsedAttr::AT_CUDADevice:
7862*e038c9c4Sjoerg     handleDeviceAttr(S, D, AL);
78637330f729Sjoerg     break;
7864*e038c9c4Sjoerg   case ParsedAttr::AT_HIPManaged:
7865*e038c9c4Sjoerg     handleManagedAttr(S, D, AL);
78667330f729Sjoerg     break;
78677330f729Sjoerg   case ParsedAttr::AT_GNUInline:
78687330f729Sjoerg     handleGNUInlineAttr(S, D, AL);
78697330f729Sjoerg     break;
78707330f729Sjoerg   case ParsedAttr::AT_CUDALaunchBounds:
78717330f729Sjoerg     handleLaunchBoundsAttr(S, D, AL);
78727330f729Sjoerg     break;
78737330f729Sjoerg   case ParsedAttr::AT_Restrict:
78747330f729Sjoerg     handleRestrictAttr(S, D, AL);
78757330f729Sjoerg     break;
78767330f729Sjoerg   case ParsedAttr::AT_Mode:
78777330f729Sjoerg     handleModeAttr(S, D, AL);
78787330f729Sjoerg     break;
78797330f729Sjoerg   case ParsedAttr::AT_NonNull:
78807330f729Sjoerg     if (auto *PVD = dyn_cast<ParmVarDecl>(D))
78817330f729Sjoerg       handleNonNullAttrParameter(S, PVD, AL);
78827330f729Sjoerg     else
78837330f729Sjoerg       handleNonNullAttr(S, D, AL);
78847330f729Sjoerg     break;
78857330f729Sjoerg   case ParsedAttr::AT_ReturnsNonNull:
78867330f729Sjoerg     handleReturnsNonNullAttr(S, D, AL);
78877330f729Sjoerg     break;
78887330f729Sjoerg   case ParsedAttr::AT_NoEscape:
78897330f729Sjoerg     handleNoEscapeAttr(S, D, AL);
78907330f729Sjoerg     break;
78917330f729Sjoerg   case ParsedAttr::AT_AssumeAligned:
78927330f729Sjoerg     handleAssumeAlignedAttr(S, D, AL);
78937330f729Sjoerg     break;
78947330f729Sjoerg   case ParsedAttr::AT_AllocAlign:
78957330f729Sjoerg     handleAllocAlignAttr(S, D, AL);
78967330f729Sjoerg     break;
78977330f729Sjoerg   case ParsedAttr::AT_Ownership:
78987330f729Sjoerg     handleOwnershipAttr(S, D, AL);
78997330f729Sjoerg     break;
79007330f729Sjoerg   case ParsedAttr::AT_Naked:
79017330f729Sjoerg     handleNakedAttr(S, D, AL);
79027330f729Sjoerg     break;
79037330f729Sjoerg   case ParsedAttr::AT_NoReturn:
79047330f729Sjoerg     handleNoReturnAttr(S, D, AL);
79057330f729Sjoerg     break;
79067330f729Sjoerg   case ParsedAttr::AT_AnyX86NoCfCheck:
79077330f729Sjoerg     handleNoCfCheckAttr(S, D, AL);
79087330f729Sjoerg     break;
79097330f729Sjoerg   case ParsedAttr::AT_NoThrow:
79107330f729Sjoerg     if (!AL.isUsedAsTypeAttr())
79117330f729Sjoerg       handleSimpleAttribute<NoThrowAttr>(S, D, AL);
79127330f729Sjoerg     break;
79137330f729Sjoerg   case ParsedAttr::AT_CUDAShared:
79147330f729Sjoerg     handleSharedAttr(S, D, AL);
79157330f729Sjoerg     break;
79167330f729Sjoerg   case ParsedAttr::AT_VecReturn:
79177330f729Sjoerg     handleVecReturnAttr(S, D, AL);
79187330f729Sjoerg     break;
79197330f729Sjoerg   case ParsedAttr::AT_ObjCOwnership:
79207330f729Sjoerg     handleObjCOwnershipAttr(S, D, AL);
79217330f729Sjoerg     break;
79227330f729Sjoerg   case ParsedAttr::AT_ObjCPreciseLifetime:
79237330f729Sjoerg     handleObjCPreciseLifetimeAttr(S, D, AL);
79247330f729Sjoerg     break;
79257330f729Sjoerg   case ParsedAttr::AT_ObjCReturnsInnerPointer:
79267330f729Sjoerg     handleObjCReturnsInnerPointerAttr(S, D, AL);
79277330f729Sjoerg     break;
79287330f729Sjoerg   case ParsedAttr::AT_ObjCRequiresSuper:
79297330f729Sjoerg     handleObjCRequiresSuperAttr(S, D, AL);
79307330f729Sjoerg     break;
79317330f729Sjoerg   case ParsedAttr::AT_ObjCBridge:
79327330f729Sjoerg     handleObjCBridgeAttr(S, D, AL);
79337330f729Sjoerg     break;
79347330f729Sjoerg   case ParsedAttr::AT_ObjCBridgeMutable:
79357330f729Sjoerg     handleObjCBridgeMutableAttr(S, D, AL);
79367330f729Sjoerg     break;
79377330f729Sjoerg   case ParsedAttr::AT_ObjCBridgeRelated:
79387330f729Sjoerg     handleObjCBridgeRelatedAttr(S, D, AL);
79397330f729Sjoerg     break;
79407330f729Sjoerg   case ParsedAttr::AT_ObjCDesignatedInitializer:
79417330f729Sjoerg     handleObjCDesignatedInitializer(S, D, AL);
79427330f729Sjoerg     break;
79437330f729Sjoerg   case ParsedAttr::AT_ObjCRuntimeName:
79447330f729Sjoerg     handleObjCRuntimeName(S, D, AL);
79457330f729Sjoerg     break;
79467330f729Sjoerg   case ParsedAttr::AT_ObjCBoxable:
79477330f729Sjoerg     handleObjCBoxable(S, D, AL);
79487330f729Sjoerg     break;
7949*e038c9c4Sjoerg   case ParsedAttr::AT_NSErrorDomain:
7950*e038c9c4Sjoerg     handleNSErrorDomain(S, D, AL);
79517330f729Sjoerg     break;
79527330f729Sjoerg   case ParsedAttr::AT_CFConsumed:
79537330f729Sjoerg   case ParsedAttr::AT_NSConsumed:
79547330f729Sjoerg   case ParsedAttr::AT_OSConsumed:
79557330f729Sjoerg     S.AddXConsumedAttr(D, AL, parsedAttrToRetainOwnershipKind(AL),
79567330f729Sjoerg                        /*IsTemplateInstantiation=*/false);
79577330f729Sjoerg     break;
79587330f729Sjoerg   case ParsedAttr::AT_OSReturnsRetainedOnZero:
79597330f729Sjoerg     handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnZeroAttr>(
79607330f729Sjoerg         S, D, AL, isValidOSObjectOutParameter(D),
79617330f729Sjoerg         diag::warn_ns_attribute_wrong_parameter_type,
79627330f729Sjoerg         /*Extra Args=*/AL, /*pointer-to-OSObject-pointer*/ 3, AL.getRange());
79637330f729Sjoerg     break;
79647330f729Sjoerg   case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
79657330f729Sjoerg     handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnNonZeroAttr>(
79667330f729Sjoerg         S, D, AL, isValidOSObjectOutParameter(D),
79677330f729Sjoerg         diag::warn_ns_attribute_wrong_parameter_type,
79687330f729Sjoerg         /*Extra Args=*/AL, /*pointer-to-OSObject-poointer*/ 3, AL.getRange());
79697330f729Sjoerg     break;
79707330f729Sjoerg   case ParsedAttr::AT_NSReturnsAutoreleased:
79717330f729Sjoerg   case ParsedAttr::AT_NSReturnsNotRetained:
79727330f729Sjoerg   case ParsedAttr::AT_NSReturnsRetained:
79737330f729Sjoerg   case ParsedAttr::AT_CFReturnsNotRetained:
79747330f729Sjoerg   case ParsedAttr::AT_CFReturnsRetained:
79757330f729Sjoerg   case ParsedAttr::AT_OSReturnsNotRetained:
79767330f729Sjoerg   case ParsedAttr::AT_OSReturnsRetained:
79777330f729Sjoerg     handleXReturnsXRetainedAttr(S, D, AL);
79787330f729Sjoerg     break;
79797330f729Sjoerg   case ParsedAttr::AT_WorkGroupSizeHint:
79807330f729Sjoerg     handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL);
79817330f729Sjoerg     break;
79827330f729Sjoerg   case ParsedAttr::AT_ReqdWorkGroupSize:
79837330f729Sjoerg     handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL);
79847330f729Sjoerg     break;
79857330f729Sjoerg   case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize:
79867330f729Sjoerg     handleSubGroupSize(S, D, AL);
79877330f729Sjoerg     break;
79887330f729Sjoerg   case ParsedAttr::AT_VecTypeHint:
79897330f729Sjoerg     handleVecTypeHint(S, D, AL);
79907330f729Sjoerg     break;
79917330f729Sjoerg   case ParsedAttr::AT_InitPriority:
79927330f729Sjoerg       handleInitPriorityAttr(S, D, AL);
79937330f729Sjoerg     break;
79947330f729Sjoerg   case ParsedAttr::AT_Packed:
79957330f729Sjoerg     handlePackedAttr(S, D, AL);
79967330f729Sjoerg     break;
7997*e038c9c4Sjoerg   case ParsedAttr::AT_PreferredName:
7998*e038c9c4Sjoerg     handlePreferredName(S, D, AL);
7999*e038c9c4Sjoerg     break;
80007330f729Sjoerg   case ParsedAttr::AT_Section:
80017330f729Sjoerg     handleSectionAttr(S, D, AL);
80027330f729Sjoerg     break;
80037330f729Sjoerg   case ParsedAttr::AT_CodeSeg:
80047330f729Sjoerg     handleCodeSegAttr(S, D, AL);
80057330f729Sjoerg     break;
80067330f729Sjoerg   case ParsedAttr::AT_Target:
80077330f729Sjoerg     handleTargetAttr(S, D, AL);
80087330f729Sjoerg     break;
80097330f729Sjoerg   case ParsedAttr::AT_MinVectorWidth:
80107330f729Sjoerg     handleMinVectorWidthAttr(S, D, AL);
80117330f729Sjoerg     break;
80127330f729Sjoerg   case ParsedAttr::AT_Unavailable:
80137330f729Sjoerg     handleAttrWithMessage<UnavailableAttr>(S, D, AL);
80147330f729Sjoerg     break;
8015*e038c9c4Sjoerg   case ParsedAttr::AT_Assumption:
8016*e038c9c4Sjoerg     handleAssumumptionAttr(S, D, AL);
80177330f729Sjoerg     break;
8018*e038c9c4Sjoerg   case ParsedAttr::AT_ObjCDirect:
8019*e038c9c4Sjoerg     handleObjCDirectAttr(S, D, AL);
80207330f729Sjoerg     break;
8021*e038c9c4Sjoerg   case ParsedAttr::AT_ObjCDirectMembers:
8022*e038c9c4Sjoerg     handleObjCDirectMembersAttr(S, D, AL);
8023*e038c9c4Sjoerg     handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
80247330f729Sjoerg     break;
80257330f729Sjoerg   case ParsedAttr::AT_ObjCExplicitProtocolImpl:
80267330f729Sjoerg     handleObjCSuppresProtocolAttr(S, D, AL);
80277330f729Sjoerg     break;
80287330f729Sjoerg   case ParsedAttr::AT_Unused:
80297330f729Sjoerg     handleUnusedAttr(S, D, AL);
80307330f729Sjoerg     break;
80317330f729Sjoerg   case ParsedAttr::AT_Visibility:
80327330f729Sjoerg     handleVisibilityAttr(S, D, AL, false);
80337330f729Sjoerg     break;
80347330f729Sjoerg   case ParsedAttr::AT_TypeVisibility:
80357330f729Sjoerg     handleVisibilityAttr(S, D, AL, true);
80367330f729Sjoerg     break;
80377330f729Sjoerg   case ParsedAttr::AT_WarnUnusedResult:
80387330f729Sjoerg     handleWarnUnusedResult(S, D, AL);
80397330f729Sjoerg     break;
80407330f729Sjoerg   case ParsedAttr::AT_WeakRef:
80417330f729Sjoerg     handleWeakRefAttr(S, D, AL);
80427330f729Sjoerg     break;
80437330f729Sjoerg   case ParsedAttr::AT_WeakImport:
80447330f729Sjoerg     handleWeakImportAttr(S, D, AL);
80457330f729Sjoerg     break;
80467330f729Sjoerg   case ParsedAttr::AT_TransparentUnion:
80477330f729Sjoerg     handleTransparentUnionAttr(S, D, AL);
80487330f729Sjoerg     break;
80497330f729Sjoerg   case ParsedAttr::AT_ObjCMethodFamily:
80507330f729Sjoerg     handleObjCMethodFamilyAttr(S, D, AL);
80517330f729Sjoerg     break;
80527330f729Sjoerg   case ParsedAttr::AT_ObjCNSObject:
80537330f729Sjoerg     handleObjCNSObject(S, D, AL);
80547330f729Sjoerg     break;
80557330f729Sjoerg   case ParsedAttr::AT_ObjCIndependentClass:
80567330f729Sjoerg     handleObjCIndependentClass(S, D, AL);
80577330f729Sjoerg     break;
80587330f729Sjoerg   case ParsedAttr::AT_Blocks:
80597330f729Sjoerg     handleBlocksAttr(S, D, AL);
80607330f729Sjoerg     break;
80617330f729Sjoerg   case ParsedAttr::AT_Sentinel:
80627330f729Sjoerg     handleSentinelAttr(S, D, AL);
80637330f729Sjoerg     break;
80647330f729Sjoerg   case ParsedAttr::AT_Cleanup:
80657330f729Sjoerg     handleCleanupAttr(S, D, AL);
80667330f729Sjoerg     break;
80677330f729Sjoerg   case ParsedAttr::AT_NoDebug:
80687330f729Sjoerg     handleNoDebugAttr(S, D, AL);
80697330f729Sjoerg     break;
8070*e038c9c4Sjoerg   case ParsedAttr::AT_CmseNSEntry:
8071*e038c9c4Sjoerg     handleCmseNSEntryAttr(S, D, AL);
80727330f729Sjoerg     break;
80737330f729Sjoerg   case ParsedAttr::AT_StdCall:
80747330f729Sjoerg   case ParsedAttr::AT_CDecl:
80757330f729Sjoerg   case ParsedAttr::AT_FastCall:
80767330f729Sjoerg   case ParsedAttr::AT_ThisCall:
80777330f729Sjoerg   case ParsedAttr::AT_Pascal:
80787330f729Sjoerg   case ParsedAttr::AT_RegCall:
80797330f729Sjoerg   case ParsedAttr::AT_SwiftCall:
80807330f729Sjoerg   case ParsedAttr::AT_VectorCall:
80817330f729Sjoerg   case ParsedAttr::AT_MSABI:
80827330f729Sjoerg   case ParsedAttr::AT_SysVABI:
80837330f729Sjoerg   case ParsedAttr::AT_Pcs:
80847330f729Sjoerg   case ParsedAttr::AT_IntelOclBicc:
80857330f729Sjoerg   case ParsedAttr::AT_PreserveMost:
80867330f729Sjoerg   case ParsedAttr::AT_PreserveAll:
80877330f729Sjoerg   case ParsedAttr::AT_AArch64VectorPcs:
80887330f729Sjoerg     handleCallConvAttr(S, D, AL);
80897330f729Sjoerg     break;
80907330f729Sjoerg   case ParsedAttr::AT_Suppress:
80917330f729Sjoerg     handleSuppressAttr(S, D, AL);
80927330f729Sjoerg     break;
80937330f729Sjoerg   case ParsedAttr::AT_Owner:
80947330f729Sjoerg   case ParsedAttr::AT_Pointer:
80957330f729Sjoerg     handleLifetimeCategoryAttr(S, D, AL);
80967330f729Sjoerg     break;
80977330f729Sjoerg   case ParsedAttr::AT_OpenCLAccess:
80987330f729Sjoerg     handleOpenCLAccessAttr(S, D, AL);
80997330f729Sjoerg     break;
81007330f729Sjoerg   case ParsedAttr::AT_OpenCLNoSVM:
81017330f729Sjoerg     handleOpenCLNoSVMAttr(S, D, AL);
81027330f729Sjoerg     break;
81037330f729Sjoerg   case ParsedAttr::AT_SwiftContext:
81047330f729Sjoerg     S.AddParameterABIAttr(D, AL, ParameterABI::SwiftContext);
81057330f729Sjoerg     break;
81067330f729Sjoerg   case ParsedAttr::AT_SwiftErrorResult:
81077330f729Sjoerg     S.AddParameterABIAttr(D, AL, ParameterABI::SwiftErrorResult);
81087330f729Sjoerg     break;
81097330f729Sjoerg   case ParsedAttr::AT_SwiftIndirectResult:
81107330f729Sjoerg     S.AddParameterABIAttr(D, AL, ParameterABI::SwiftIndirectResult);
81117330f729Sjoerg     break;
81127330f729Sjoerg   case ParsedAttr::AT_InternalLinkage:
81137330f729Sjoerg     handleInternalLinkageAttr(S, D, AL);
81147330f729Sjoerg     break;
81157330f729Sjoerg 
81167330f729Sjoerg   // Microsoft attributes:
81177330f729Sjoerg   case ParsedAttr::AT_LayoutVersion:
81187330f729Sjoerg     handleLayoutVersion(S, D, AL);
81197330f729Sjoerg     break;
81207330f729Sjoerg   case ParsedAttr::AT_Uuid:
81217330f729Sjoerg     handleUuidAttr(S, D, AL);
81227330f729Sjoerg     break;
81237330f729Sjoerg   case ParsedAttr::AT_MSInheritance:
81247330f729Sjoerg     handleMSInheritanceAttr(S, D, AL);
81257330f729Sjoerg     break;
81267330f729Sjoerg   case ParsedAttr::AT_Thread:
81277330f729Sjoerg     handleDeclspecThreadAttr(S, D, AL);
81287330f729Sjoerg     break;
81297330f729Sjoerg 
81307330f729Sjoerg   case ParsedAttr::AT_AbiTag:
81317330f729Sjoerg     handleAbiTagAttr(S, D, AL);
81327330f729Sjoerg     break;
8133*e038c9c4Sjoerg   case ParsedAttr::AT_CFGuard:
8134*e038c9c4Sjoerg     handleCFGuardAttr(S, D, AL);
8135*e038c9c4Sjoerg     break;
81367330f729Sjoerg 
81377330f729Sjoerg   // Thread safety attributes:
81387330f729Sjoerg   case ParsedAttr::AT_AssertExclusiveLock:
81397330f729Sjoerg     handleAssertExclusiveLockAttr(S, D, AL);
81407330f729Sjoerg     break;
81417330f729Sjoerg   case ParsedAttr::AT_AssertSharedLock:
81427330f729Sjoerg     handleAssertSharedLockAttr(S, D, AL);
81437330f729Sjoerg     break;
81447330f729Sjoerg   case ParsedAttr::AT_PtGuardedVar:
81457330f729Sjoerg     handlePtGuardedVarAttr(S, D, AL);
81467330f729Sjoerg     break;
81477330f729Sjoerg   case ParsedAttr::AT_NoSanitize:
81487330f729Sjoerg     handleNoSanitizeAttr(S, D, AL);
81497330f729Sjoerg     break;
81507330f729Sjoerg   case ParsedAttr::AT_NoSanitizeSpecific:
81517330f729Sjoerg     handleNoSanitizeSpecificAttr(S, D, AL);
81527330f729Sjoerg     break;
81537330f729Sjoerg   case ParsedAttr::AT_GuardedBy:
81547330f729Sjoerg     handleGuardedByAttr(S, D, AL);
81557330f729Sjoerg     break;
81567330f729Sjoerg   case ParsedAttr::AT_PtGuardedBy:
81577330f729Sjoerg     handlePtGuardedByAttr(S, D, AL);
81587330f729Sjoerg     break;
81597330f729Sjoerg   case ParsedAttr::AT_ExclusiveTrylockFunction:
81607330f729Sjoerg     handleExclusiveTrylockFunctionAttr(S, D, AL);
81617330f729Sjoerg     break;
81627330f729Sjoerg   case ParsedAttr::AT_LockReturned:
81637330f729Sjoerg     handleLockReturnedAttr(S, D, AL);
81647330f729Sjoerg     break;
81657330f729Sjoerg   case ParsedAttr::AT_LocksExcluded:
81667330f729Sjoerg     handleLocksExcludedAttr(S, D, AL);
81677330f729Sjoerg     break;
81687330f729Sjoerg   case ParsedAttr::AT_SharedTrylockFunction:
81697330f729Sjoerg     handleSharedTrylockFunctionAttr(S, D, AL);
81707330f729Sjoerg     break;
81717330f729Sjoerg   case ParsedAttr::AT_AcquiredBefore:
81727330f729Sjoerg     handleAcquiredBeforeAttr(S, D, AL);
81737330f729Sjoerg     break;
81747330f729Sjoerg   case ParsedAttr::AT_AcquiredAfter:
81757330f729Sjoerg     handleAcquiredAfterAttr(S, D, AL);
81767330f729Sjoerg     break;
81777330f729Sjoerg 
81787330f729Sjoerg   // Capability analysis attributes.
81797330f729Sjoerg   case ParsedAttr::AT_Capability:
81807330f729Sjoerg   case ParsedAttr::AT_Lockable:
81817330f729Sjoerg     handleCapabilityAttr(S, D, AL);
81827330f729Sjoerg     break;
81837330f729Sjoerg   case ParsedAttr::AT_RequiresCapability:
81847330f729Sjoerg     handleRequiresCapabilityAttr(S, D, AL);
81857330f729Sjoerg     break;
81867330f729Sjoerg 
81877330f729Sjoerg   case ParsedAttr::AT_AssertCapability:
81887330f729Sjoerg     handleAssertCapabilityAttr(S, D, AL);
81897330f729Sjoerg     break;
81907330f729Sjoerg   case ParsedAttr::AT_AcquireCapability:
81917330f729Sjoerg     handleAcquireCapabilityAttr(S, D, AL);
81927330f729Sjoerg     break;
81937330f729Sjoerg   case ParsedAttr::AT_ReleaseCapability:
81947330f729Sjoerg     handleReleaseCapabilityAttr(S, D, AL);
81957330f729Sjoerg     break;
81967330f729Sjoerg   case ParsedAttr::AT_TryAcquireCapability:
81977330f729Sjoerg     handleTryAcquireCapabilityAttr(S, D, AL);
81987330f729Sjoerg     break;
81997330f729Sjoerg 
82007330f729Sjoerg   // Consumed analysis attributes.
82017330f729Sjoerg   case ParsedAttr::AT_Consumable:
82027330f729Sjoerg     handleConsumableAttr(S, D, AL);
82037330f729Sjoerg     break;
82047330f729Sjoerg   case ParsedAttr::AT_CallableWhen:
82057330f729Sjoerg     handleCallableWhenAttr(S, D, AL);
82067330f729Sjoerg     break;
82077330f729Sjoerg   case ParsedAttr::AT_ParamTypestate:
82087330f729Sjoerg     handleParamTypestateAttr(S, D, AL);
82097330f729Sjoerg     break;
82107330f729Sjoerg   case ParsedAttr::AT_ReturnTypestate:
82117330f729Sjoerg     handleReturnTypestateAttr(S, D, AL);
82127330f729Sjoerg     break;
82137330f729Sjoerg   case ParsedAttr::AT_SetTypestate:
82147330f729Sjoerg     handleSetTypestateAttr(S, D, AL);
82157330f729Sjoerg     break;
82167330f729Sjoerg   case ParsedAttr::AT_TestTypestate:
82177330f729Sjoerg     handleTestTypestateAttr(S, D, AL);
82187330f729Sjoerg     break;
82197330f729Sjoerg 
82207330f729Sjoerg   // Type safety attributes.
82217330f729Sjoerg   case ParsedAttr::AT_ArgumentWithTypeTag:
82227330f729Sjoerg     handleArgumentWithTypeTagAttr(S, D, AL);
82237330f729Sjoerg     break;
82247330f729Sjoerg   case ParsedAttr::AT_TypeTagForDatatype:
82257330f729Sjoerg     handleTypeTagForDatatypeAttr(S, D, AL);
82267330f729Sjoerg     break;
8227*e038c9c4Sjoerg 
8228*e038c9c4Sjoerg   // Swift attributes.
8229*e038c9c4Sjoerg   case ParsedAttr::AT_SwiftAsyncName:
8230*e038c9c4Sjoerg     handleSwiftAsyncName(S, D, AL);
82317330f729Sjoerg     break;
8232*e038c9c4Sjoerg   case ParsedAttr::AT_SwiftAttr:
8233*e038c9c4Sjoerg     handleSwiftAttrAttr(S, D, AL);
82347330f729Sjoerg     break;
8235*e038c9c4Sjoerg   case ParsedAttr::AT_SwiftBridge:
8236*e038c9c4Sjoerg     handleSwiftBridge(S, D, AL);
8237*e038c9c4Sjoerg     break;
8238*e038c9c4Sjoerg   case ParsedAttr::AT_SwiftError:
8239*e038c9c4Sjoerg     handleSwiftError(S, D, AL);
8240*e038c9c4Sjoerg     break;
8241*e038c9c4Sjoerg   case ParsedAttr::AT_SwiftName:
8242*e038c9c4Sjoerg     handleSwiftName(S, D, AL);
8243*e038c9c4Sjoerg     break;
8244*e038c9c4Sjoerg   case ParsedAttr::AT_SwiftNewType:
8245*e038c9c4Sjoerg     handleSwiftNewType(S, D, AL);
8246*e038c9c4Sjoerg     break;
8247*e038c9c4Sjoerg   case ParsedAttr::AT_SwiftAsync:
8248*e038c9c4Sjoerg     handleSwiftAsyncAttr(S, D, AL);
8249*e038c9c4Sjoerg     break;
8250*e038c9c4Sjoerg   case ParsedAttr::AT_SwiftAsyncError:
8251*e038c9c4Sjoerg     handleSwiftAsyncError(S, D, AL);
8252*e038c9c4Sjoerg     break;
8253*e038c9c4Sjoerg 
82547330f729Sjoerg   // XRay attributes.
82557330f729Sjoerg   case ParsedAttr::AT_XRayLogArgs:
82567330f729Sjoerg     handleXRayLogArgsAttr(S, D, AL);
82577330f729Sjoerg     break;
82587330f729Sjoerg 
8259*e038c9c4Sjoerg   case ParsedAttr::AT_PatchableFunctionEntry:
8260*e038c9c4Sjoerg     handlePatchableFunctionEntryAttr(S, D, AL);
82617330f729Sjoerg     break;
82627330f729Sjoerg 
82637330f729Sjoerg   case ParsedAttr::AT_AlwaysDestroy:
82647330f729Sjoerg   case ParsedAttr::AT_NoDestroy:
82657330f729Sjoerg     handleDestroyAttr(S, D, AL);
82667330f729Sjoerg     break;
82677330f729Sjoerg 
82687330f729Sjoerg   case ParsedAttr::AT_Uninitialized:
82697330f729Sjoerg     handleUninitializedAttr(S, D, AL);
82707330f729Sjoerg     break;
82717330f729Sjoerg 
82727330f729Sjoerg   case ParsedAttr::AT_ObjCExternallyRetained:
82737330f729Sjoerg     handleObjCExternallyRetainedAttr(S, D, AL);
82747330f729Sjoerg     break;
82757330f729Sjoerg 
82767330f729Sjoerg   case ParsedAttr::AT_MIGServerRoutine:
82777330f729Sjoerg     handleMIGServerRoutineAttr(S, D, AL);
82787330f729Sjoerg     break;
82797330f729Sjoerg 
82807330f729Sjoerg   case ParsedAttr::AT_MSAllocator:
82817330f729Sjoerg     handleMSAllocatorAttr(S, D, AL);
82827330f729Sjoerg     break;
82837330f729Sjoerg 
8284*e038c9c4Sjoerg   case ParsedAttr::AT_ArmBuiltinAlias:
8285*e038c9c4Sjoerg     handleArmBuiltinAliasAttr(S, D, AL);
8286*e038c9c4Sjoerg     break;
8287*e038c9c4Sjoerg 
8288*e038c9c4Sjoerg   case ParsedAttr::AT_AcquireHandle:
8289*e038c9c4Sjoerg     handleAcquireHandleAttr(S, D, AL);
8290*e038c9c4Sjoerg     break;
8291*e038c9c4Sjoerg 
8292*e038c9c4Sjoerg   case ParsedAttr::AT_ReleaseHandle:
8293*e038c9c4Sjoerg     handleHandleAttr<ReleaseHandleAttr>(S, D, AL);
8294*e038c9c4Sjoerg     break;
8295*e038c9c4Sjoerg 
8296*e038c9c4Sjoerg   case ParsedAttr::AT_UseHandle:
8297*e038c9c4Sjoerg     handleHandleAttr<UseHandleAttr>(S, D, AL);
8298*e038c9c4Sjoerg     break;
8299*e038c9c4Sjoerg 
8300*e038c9c4Sjoerg   case ParsedAttr::AT_EnforceTCB:
8301*e038c9c4Sjoerg     handleEnforceTCBAttr<EnforceTCBAttr, EnforceTCBLeafAttr>(S, D, AL);
8302*e038c9c4Sjoerg     break;
8303*e038c9c4Sjoerg 
8304*e038c9c4Sjoerg   case ParsedAttr::AT_EnforceTCBLeaf:
8305*e038c9c4Sjoerg     handleEnforceTCBAttr<EnforceTCBLeafAttr, EnforceTCBAttr>(S, D, AL);
8306*e038c9c4Sjoerg     break;
8307*e038c9c4Sjoerg 
8308*e038c9c4Sjoerg   case ParsedAttr::AT_BuiltinAlias:
8309*e038c9c4Sjoerg     handleBuiltinAliasAttr(S, D, AL);
83107330f729Sjoerg     break;
83117330f729Sjoerg   }
83127330f729Sjoerg }
83137330f729Sjoerg 
83147330f729Sjoerg /// ProcessDeclAttributeList - Apply all the decl attributes in the specified
83157330f729Sjoerg /// attribute list to the specified decl, ignoring any type attributes.
ProcessDeclAttributeList(Scope * S,Decl * D,const ParsedAttributesView & AttrList,bool IncludeCXX11Attributes)83167330f729Sjoerg void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
83177330f729Sjoerg                                     const ParsedAttributesView &AttrList,
83187330f729Sjoerg                                     bool IncludeCXX11Attributes) {
83197330f729Sjoerg   if (AttrList.empty())
83207330f729Sjoerg     return;
83217330f729Sjoerg 
83227330f729Sjoerg   for (const ParsedAttr &AL : AttrList)
83237330f729Sjoerg     ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes);
83247330f729Sjoerg 
83257330f729Sjoerg   // FIXME: We should be able to handle these cases in TableGen.
83267330f729Sjoerg   // GCC accepts
83277330f729Sjoerg   // static int a9 __attribute__((weakref));
83287330f729Sjoerg   // but that looks really pointless. We reject it.
83297330f729Sjoerg   if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
83307330f729Sjoerg     Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias)
83317330f729Sjoerg         << cast<NamedDecl>(D);
83327330f729Sjoerg     D->dropAttr<WeakRefAttr>();
83337330f729Sjoerg     return;
83347330f729Sjoerg   }
83357330f729Sjoerg 
83367330f729Sjoerg   // FIXME: We should be able to handle this in TableGen as well. It would be
83377330f729Sjoerg   // good to have a way to specify "these attributes must appear as a group",
83387330f729Sjoerg   // for these. Additionally, it would be good to have a way to specify "these
83397330f729Sjoerg   // attribute must never appear as a group" for attributes like cold and hot.
83407330f729Sjoerg   if (!D->hasAttr<OpenCLKernelAttr>()) {
83417330f729Sjoerg     // These attributes cannot be applied to a non-kernel function.
83427330f729Sjoerg     if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
83437330f729Sjoerg       // FIXME: This emits a different error message than
83447330f729Sjoerg       // diag::err_attribute_wrong_decl_type + ExpectedKernelFunction.
83457330f729Sjoerg       Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
83467330f729Sjoerg       D->setInvalidDecl();
83477330f729Sjoerg     } else if (const auto *A = D->getAttr<WorkGroupSizeHintAttr>()) {
83487330f729Sjoerg       Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
83497330f729Sjoerg       D->setInvalidDecl();
83507330f729Sjoerg     } else if (const auto *A = D->getAttr<VecTypeHintAttr>()) {
83517330f729Sjoerg       Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
83527330f729Sjoerg       D->setInvalidDecl();
83537330f729Sjoerg     } else if (const auto *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) {
83547330f729Sjoerg       Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
83557330f729Sjoerg       D->setInvalidDecl();
83567330f729Sjoerg     } else if (!D->hasAttr<CUDAGlobalAttr>()) {
83577330f729Sjoerg       if (const auto *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
83587330f729Sjoerg         Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
83597330f729Sjoerg             << A << ExpectedKernelFunction;
83607330f729Sjoerg         D->setInvalidDecl();
83617330f729Sjoerg       } else if (const auto *A = D->getAttr<AMDGPUWavesPerEUAttr>()) {
83627330f729Sjoerg         Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
83637330f729Sjoerg             << A << ExpectedKernelFunction;
83647330f729Sjoerg         D->setInvalidDecl();
83657330f729Sjoerg       } else if (const auto *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
83667330f729Sjoerg         Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
83677330f729Sjoerg             << A << ExpectedKernelFunction;
83687330f729Sjoerg         D->setInvalidDecl();
83697330f729Sjoerg       } else if (const auto *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
83707330f729Sjoerg         Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
83717330f729Sjoerg             << A << ExpectedKernelFunction;
83727330f729Sjoerg         D->setInvalidDecl();
83737330f729Sjoerg       }
83747330f729Sjoerg     }
83757330f729Sjoerg   }
83767330f729Sjoerg 
83777330f729Sjoerg   // Do this check after processing D's attributes because the attribute
83787330f729Sjoerg   // objc_method_family can change whether the given method is in the init
83797330f729Sjoerg   // family, and it can be applied after objc_designated_initializer. This is a
83807330f729Sjoerg   // bit of a hack, but we need it to be compatible with versions of clang that
83817330f729Sjoerg   // processed the attribute list in the wrong order.
83827330f729Sjoerg   if (D->hasAttr<ObjCDesignatedInitializerAttr>() &&
83837330f729Sjoerg       cast<ObjCMethodDecl>(D)->getMethodFamily() != OMF_init) {
83847330f729Sjoerg     Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
83857330f729Sjoerg     D->dropAttr<ObjCDesignatedInitializerAttr>();
83867330f729Sjoerg   }
83877330f729Sjoerg }
83887330f729Sjoerg 
8389*e038c9c4Sjoerg // Helper for delayed processing TransparentUnion or BPFPreserveAccessIndexAttr
8390*e038c9c4Sjoerg // attribute.
ProcessDeclAttributeDelayed(Decl * D,const ParsedAttributesView & AttrList)83917330f729Sjoerg void Sema::ProcessDeclAttributeDelayed(Decl *D,
83927330f729Sjoerg                                        const ParsedAttributesView &AttrList) {
83937330f729Sjoerg   for (const ParsedAttr &AL : AttrList)
83947330f729Sjoerg     if (AL.getKind() == ParsedAttr::AT_TransparentUnion) {
83957330f729Sjoerg       handleTransparentUnionAttr(*this, D, AL);
83967330f729Sjoerg       break;
83977330f729Sjoerg     }
8398*e038c9c4Sjoerg 
8399*e038c9c4Sjoerg   // For BPFPreserveAccessIndexAttr, we want to populate the attributes
8400*e038c9c4Sjoerg   // to fields and inner records as well.
8401*e038c9c4Sjoerg   if (D && D->hasAttr<BPFPreserveAccessIndexAttr>())
8402*e038c9c4Sjoerg     handleBPFPreserveAIRecord(*this, cast<RecordDecl>(D));
84037330f729Sjoerg }
84047330f729Sjoerg 
84057330f729Sjoerg // Annotation attributes are the only attributes allowed after an access
84067330f729Sjoerg // specifier.
ProcessAccessDeclAttributeList(AccessSpecDecl * ASDecl,const ParsedAttributesView & AttrList)84077330f729Sjoerg bool Sema::ProcessAccessDeclAttributeList(
84087330f729Sjoerg     AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) {
84097330f729Sjoerg   for (const ParsedAttr &AL : AttrList) {
84107330f729Sjoerg     if (AL.getKind() == ParsedAttr::AT_Annotate) {
84117330f729Sjoerg       ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute());
84127330f729Sjoerg     } else {
84137330f729Sjoerg       Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec);
84147330f729Sjoerg       return true;
84157330f729Sjoerg     }
84167330f729Sjoerg   }
84177330f729Sjoerg   return false;
84187330f729Sjoerg }
84197330f729Sjoerg 
84207330f729Sjoerg /// checkUnusedDeclAttributes - Check a list of attributes to see if it
84217330f729Sjoerg /// contains any decl attributes that we should warn about.
checkUnusedDeclAttributes(Sema & S,const ParsedAttributesView & A)84227330f729Sjoerg static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) {
84237330f729Sjoerg   for (const ParsedAttr &AL : A) {
84247330f729Sjoerg     // Only warn if the attribute is an unignored, non-type attribute.
84257330f729Sjoerg     if (AL.isUsedAsTypeAttr() || AL.isInvalid())
84267330f729Sjoerg       continue;
84277330f729Sjoerg     if (AL.getKind() == ParsedAttr::IgnoredAttribute)
84287330f729Sjoerg       continue;
84297330f729Sjoerg 
84307330f729Sjoerg     if (AL.getKind() == ParsedAttr::UnknownAttribute) {
84317330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
84327330f729Sjoerg           << AL << AL.getRange();
84337330f729Sjoerg     } else {
84347330f729Sjoerg       S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) << AL
84357330f729Sjoerg                                                             << AL.getRange();
84367330f729Sjoerg     }
84377330f729Sjoerg   }
84387330f729Sjoerg }
84397330f729Sjoerg 
84407330f729Sjoerg /// checkUnusedDeclAttributes - Given a declarator which is not being
84417330f729Sjoerg /// used to build a declaration, complain about any decl attributes
84427330f729Sjoerg /// which might be lying around on it.
checkUnusedDeclAttributes(Declarator & D)84437330f729Sjoerg void Sema::checkUnusedDeclAttributes(Declarator &D) {
84447330f729Sjoerg   ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes());
84457330f729Sjoerg   ::checkUnusedDeclAttributes(*this, D.getAttributes());
84467330f729Sjoerg   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
84477330f729Sjoerg     ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs());
84487330f729Sjoerg }
84497330f729Sjoerg 
84507330f729Sjoerg /// DeclClonePragmaWeak - clone existing decl (maybe definition),
84517330f729Sjoerg /// \#pragma weak needs a non-definition decl and source may not have one.
DeclClonePragmaWeak(NamedDecl * ND,IdentifierInfo * II,SourceLocation Loc)84527330f729Sjoerg NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
84537330f729Sjoerg                                       SourceLocation Loc) {
84547330f729Sjoerg   assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
84557330f729Sjoerg   NamedDecl *NewD = nullptr;
84567330f729Sjoerg   if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
84577330f729Sjoerg     FunctionDecl *NewFD;
84587330f729Sjoerg     // FIXME: Missing call to CheckFunctionDeclaration().
84597330f729Sjoerg     // FIXME: Mangling?
84607330f729Sjoerg     // FIXME: Is the qualifier info correct?
84617330f729Sjoerg     // FIXME: Is the DeclContext correct?
84627330f729Sjoerg     NewFD = FunctionDecl::Create(
84637330f729Sjoerg         FD->getASTContext(), FD->getDeclContext(), Loc, Loc,
84647330f729Sjoerg         DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None,
8465*e038c9c4Sjoerg         false /*isInlineSpecified*/, FD->hasPrototype(),
8466*e038c9c4Sjoerg         ConstexprSpecKind::Unspecified, FD->getTrailingRequiresClause());
84677330f729Sjoerg     NewD = NewFD;
84687330f729Sjoerg 
84697330f729Sjoerg     if (FD->getQualifier())
84707330f729Sjoerg       NewFD->setQualifierInfo(FD->getQualifierLoc());
84717330f729Sjoerg 
84727330f729Sjoerg     // Fake up parameter variables; they are declared as if this were
84737330f729Sjoerg     // a typedef.
84747330f729Sjoerg     QualType FDTy = FD->getType();
84757330f729Sjoerg     if (const auto *FT = FDTy->getAs<FunctionProtoType>()) {
84767330f729Sjoerg       SmallVector<ParmVarDecl*, 16> Params;
84777330f729Sjoerg       for (const auto &AI : FT->param_types()) {
84787330f729Sjoerg         ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
84797330f729Sjoerg         Param->setScopeInfo(0, Params.size());
84807330f729Sjoerg         Params.push_back(Param);
84817330f729Sjoerg       }
84827330f729Sjoerg       NewFD->setParams(Params);
84837330f729Sjoerg     }
84847330f729Sjoerg   } else if (auto *VD = dyn_cast<VarDecl>(ND)) {
84857330f729Sjoerg     NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
84867330f729Sjoerg                            VD->getInnerLocStart(), VD->getLocation(), II,
84877330f729Sjoerg                            VD->getType(), VD->getTypeSourceInfo(),
84887330f729Sjoerg                            VD->getStorageClass());
84897330f729Sjoerg     if (VD->getQualifier())
84907330f729Sjoerg       cast<VarDecl>(NewD)->setQualifierInfo(VD->getQualifierLoc());
84917330f729Sjoerg   }
84927330f729Sjoerg   return NewD;
84937330f729Sjoerg }
84947330f729Sjoerg 
84957330f729Sjoerg /// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak
84967330f729Sjoerg /// applied to it, possibly with an alias.
DeclApplyPragmaWeak(Scope * S,NamedDecl * ND,WeakInfo & W)84977330f729Sjoerg void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
84987330f729Sjoerg   if (W.getUsed()) return; // only do this once
84997330f729Sjoerg   W.setUsed(true);
85007330f729Sjoerg   if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
85017330f729Sjoerg     IdentifierInfo *NDId = ND->getIdentifier();
85027330f729Sjoerg     NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
85037330f729Sjoerg     NewD->addAttr(
85047330f729Sjoerg         AliasAttr::CreateImplicit(Context, NDId->getName(), W.getLocation()));
85057330f729Sjoerg     NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation(),
85067330f729Sjoerg                                            AttributeCommonInfo::AS_Pragma));
85077330f729Sjoerg     WeakTopLevelDecl.push_back(NewD);
85087330f729Sjoerg     // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
85097330f729Sjoerg     // to insert Decl at TU scope, sorry.
85107330f729Sjoerg     DeclContext *SavedContext = CurContext;
85117330f729Sjoerg     CurContext = Context.getTranslationUnitDecl();
85127330f729Sjoerg     NewD->setDeclContext(CurContext);
85137330f729Sjoerg     NewD->setLexicalDeclContext(CurContext);
85147330f729Sjoerg     PushOnScopeChains(NewD, S);
85157330f729Sjoerg     CurContext = SavedContext;
85167330f729Sjoerg   } else { // just add weak to existing
85177330f729Sjoerg     ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation(),
85187330f729Sjoerg                                          AttributeCommonInfo::AS_Pragma));
85197330f729Sjoerg   }
85207330f729Sjoerg }
85217330f729Sjoerg 
ProcessPragmaWeak(Scope * S,Decl * D)85227330f729Sjoerg void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
85237330f729Sjoerg   // It's valid to "forward-declare" #pragma weak, in which case we
85247330f729Sjoerg   // have to do this.
85257330f729Sjoerg   LoadExternalWeakUndeclaredIdentifiers();
85267330f729Sjoerg   if (!WeakUndeclaredIdentifiers.empty()) {
85277330f729Sjoerg     NamedDecl *ND = nullptr;
85287330f729Sjoerg     if (auto *VD = dyn_cast<VarDecl>(D))
85297330f729Sjoerg       if (VD->isExternC())
85307330f729Sjoerg         ND = VD;
85317330f729Sjoerg     if (auto *FD = dyn_cast<FunctionDecl>(D))
85327330f729Sjoerg       if (FD->isExternC())
85337330f729Sjoerg         ND = FD;
85347330f729Sjoerg     if (ND) {
85357330f729Sjoerg       if (IdentifierInfo *Id = ND->getIdentifier()) {
85367330f729Sjoerg         auto I = WeakUndeclaredIdentifiers.find(Id);
85377330f729Sjoerg         if (I != WeakUndeclaredIdentifiers.end()) {
85387330f729Sjoerg           WeakInfo W = I->second;
85397330f729Sjoerg           DeclApplyPragmaWeak(S, ND, W);
85407330f729Sjoerg           WeakUndeclaredIdentifiers[Id] = W;
85417330f729Sjoerg         }
85427330f729Sjoerg       }
85437330f729Sjoerg     }
85447330f729Sjoerg   }
85457330f729Sjoerg }
85467330f729Sjoerg 
85477330f729Sjoerg /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
85487330f729Sjoerg /// it, apply them to D.  This is a bit tricky because PD can have attributes
85497330f729Sjoerg /// specified in many different places, and we need to find and apply them all.
ProcessDeclAttributes(Scope * S,Decl * D,const Declarator & PD)85507330f729Sjoerg void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
85517330f729Sjoerg   // Apply decl attributes from the DeclSpec if present.
85527330f729Sjoerg   if (!PD.getDeclSpec().getAttributes().empty())
85537330f729Sjoerg     ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes());
85547330f729Sjoerg 
85557330f729Sjoerg   // Walk the declarator structure, applying decl attributes that were in a type
85567330f729Sjoerg   // position to the decl itself.  This handles cases like:
85577330f729Sjoerg   //   int *__attr__(x)** D;
85587330f729Sjoerg   // when X is a decl attribute.
85597330f729Sjoerg   for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
85607330f729Sjoerg     ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(),
85617330f729Sjoerg                              /*IncludeCXX11Attributes=*/false);
85627330f729Sjoerg 
85637330f729Sjoerg   // Finally, apply any attributes on the decl itself.
85647330f729Sjoerg   ProcessDeclAttributeList(S, D, PD.getAttributes());
85657330f729Sjoerg 
85667330f729Sjoerg   // Apply additional attributes specified by '#pragma clang attribute'.
85677330f729Sjoerg   AddPragmaAttributes(S, D);
85687330f729Sjoerg }
85697330f729Sjoerg 
85707330f729Sjoerg /// Is the given declaration allowed to use a forbidden type?
85717330f729Sjoerg /// If so, it'll still be annotated with an attribute that makes it
85727330f729Sjoerg /// illegal to actually use.
isForbiddenTypeAllowed(Sema & S,Decl * D,const DelayedDiagnostic & diag,UnavailableAttr::ImplicitReason & reason)85737330f729Sjoerg static bool isForbiddenTypeAllowed(Sema &S, Decl *D,
85747330f729Sjoerg                                    const DelayedDiagnostic &diag,
85757330f729Sjoerg                                    UnavailableAttr::ImplicitReason &reason) {
85767330f729Sjoerg   // Private ivars are always okay.  Unfortunately, people don't
85777330f729Sjoerg   // always properly make their ivars private, even in system headers.
85787330f729Sjoerg   // Plus we need to make fields okay, too.
85797330f729Sjoerg   if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) &&
85807330f729Sjoerg       !isa<FunctionDecl>(D))
85817330f729Sjoerg     return false;
85827330f729Sjoerg 
85837330f729Sjoerg   // Silently accept unsupported uses of __weak in both user and system
85847330f729Sjoerg   // declarations when it's been disabled, for ease of integration with
85857330f729Sjoerg   // -fno-objc-arc files.  We do have to take some care against attempts
85867330f729Sjoerg   // to define such things;  for now, we've only done that for ivars
85877330f729Sjoerg   // and properties.
85887330f729Sjoerg   if ((isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D))) {
85897330f729Sjoerg     if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled ||
85907330f729Sjoerg         diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) {
85917330f729Sjoerg       reason = UnavailableAttr::IR_ForbiddenWeak;
85927330f729Sjoerg       return true;
85937330f729Sjoerg     }
85947330f729Sjoerg   }
85957330f729Sjoerg 
85967330f729Sjoerg   // Allow all sorts of things in system headers.
85977330f729Sjoerg   if (S.Context.getSourceManager().isInSystemHeader(D->getLocation())) {
85987330f729Sjoerg     // Currently, all the failures dealt with this way are due to ARC
85997330f729Sjoerg     // restrictions.
86007330f729Sjoerg     reason = UnavailableAttr::IR_ARCForbiddenType;
86017330f729Sjoerg     return true;
86027330f729Sjoerg   }
86037330f729Sjoerg 
86047330f729Sjoerg   return false;
86057330f729Sjoerg }
86067330f729Sjoerg 
86077330f729Sjoerg /// Handle a delayed forbidden-type diagnostic.
handleDelayedForbiddenType(Sema & S,DelayedDiagnostic & DD,Decl * D)86087330f729Sjoerg static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &DD,
86097330f729Sjoerg                                        Decl *D) {
86107330f729Sjoerg   auto Reason = UnavailableAttr::IR_None;
86117330f729Sjoerg   if (D && isForbiddenTypeAllowed(S, D, DD, Reason)) {
86127330f729Sjoerg     assert(Reason && "didn't set reason?");
86137330f729Sjoerg     D->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", Reason, DD.Loc));
86147330f729Sjoerg     return;
86157330f729Sjoerg   }
86167330f729Sjoerg   if (S.getLangOpts().ObjCAutoRefCount)
86177330f729Sjoerg     if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
86187330f729Sjoerg       // FIXME: we may want to suppress diagnostics for all
86197330f729Sjoerg       // kind of forbidden type messages on unavailable functions.
86207330f729Sjoerg       if (FD->hasAttr<UnavailableAttr>() &&
86217330f729Sjoerg           DD.getForbiddenTypeDiagnostic() ==
86227330f729Sjoerg               diag::err_arc_array_param_no_ownership) {
86237330f729Sjoerg         DD.Triggered = true;
86247330f729Sjoerg         return;
86257330f729Sjoerg       }
86267330f729Sjoerg     }
86277330f729Sjoerg 
86287330f729Sjoerg   S.Diag(DD.Loc, DD.getForbiddenTypeDiagnostic())
86297330f729Sjoerg       << DD.getForbiddenTypeOperand() << DD.getForbiddenTypeArgument();
86307330f729Sjoerg   DD.Triggered = true;
86317330f729Sjoerg }
86327330f729Sjoerg 
86337330f729Sjoerg 
PopParsingDeclaration(ParsingDeclState state,Decl * decl)86347330f729Sjoerg void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
86357330f729Sjoerg   assert(DelayedDiagnostics.getCurrentPool());
86367330f729Sjoerg   DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool();
86377330f729Sjoerg   DelayedDiagnostics.popWithoutEmitting(state);
86387330f729Sjoerg 
86397330f729Sjoerg   // When delaying diagnostics to run in the context of a parsed
86407330f729Sjoerg   // declaration, we only want to actually emit anything if parsing
86417330f729Sjoerg   // succeeds.
86427330f729Sjoerg   if (!decl) return;
86437330f729Sjoerg 
86447330f729Sjoerg   // We emit all the active diagnostics in this pool or any of its
86457330f729Sjoerg   // parents.  In general, we'll get one pool for the decl spec
86467330f729Sjoerg   // and a child pool for each declarator; in a decl group like:
86477330f729Sjoerg   //   deprecated_typedef foo, *bar, baz();
86487330f729Sjoerg   // only the declarator pops will be passed decls.  This is correct;
86497330f729Sjoerg   // we really do need to consider delayed diagnostics from the decl spec
86507330f729Sjoerg   // for each of the different declarations.
86517330f729Sjoerg   const DelayedDiagnosticPool *pool = &poppedPool;
86527330f729Sjoerg   do {
86537330f729Sjoerg     bool AnyAccessFailures = false;
86547330f729Sjoerg     for (DelayedDiagnosticPool::pool_iterator
86557330f729Sjoerg            i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
86567330f729Sjoerg       // This const_cast is a bit lame.  Really, Triggered should be mutable.
86577330f729Sjoerg       DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i);
86587330f729Sjoerg       if (diag.Triggered)
86597330f729Sjoerg         continue;
86607330f729Sjoerg 
86617330f729Sjoerg       switch (diag.Kind) {
86627330f729Sjoerg       case DelayedDiagnostic::Availability:
86637330f729Sjoerg         // Don't bother giving deprecation/unavailable diagnostics if
86647330f729Sjoerg         // the decl is invalid.
86657330f729Sjoerg         if (!decl->isInvalidDecl())
8666*e038c9c4Sjoerg           handleDelayedAvailabilityCheck(diag, decl);
86677330f729Sjoerg         break;
86687330f729Sjoerg 
86697330f729Sjoerg       case DelayedDiagnostic::Access:
86707330f729Sjoerg         // Only produce one access control diagnostic for a structured binding
86717330f729Sjoerg         // declaration: we don't need to tell the user that all the fields are
86727330f729Sjoerg         // inaccessible one at a time.
86737330f729Sjoerg         if (AnyAccessFailures && isa<DecompositionDecl>(decl))
86747330f729Sjoerg           continue;
86757330f729Sjoerg         HandleDelayedAccessCheck(diag, decl);
86767330f729Sjoerg         if (diag.Triggered)
86777330f729Sjoerg           AnyAccessFailures = true;
86787330f729Sjoerg         break;
86797330f729Sjoerg 
86807330f729Sjoerg       case DelayedDiagnostic::ForbiddenType:
86817330f729Sjoerg         handleDelayedForbiddenType(*this, diag, decl);
86827330f729Sjoerg         break;
86837330f729Sjoerg       }
86847330f729Sjoerg     }
86857330f729Sjoerg   } while ((pool = pool->getParent()));
86867330f729Sjoerg }
86877330f729Sjoerg 
86887330f729Sjoerg /// Given a set of delayed diagnostics, re-emit them as if they had
86897330f729Sjoerg /// been delayed in the current context instead of in the given pool.
86907330f729Sjoerg /// Essentially, this just moves them to the current pool.
redelayDiagnostics(DelayedDiagnosticPool & pool)86917330f729Sjoerg void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
86927330f729Sjoerg   DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool();
86937330f729Sjoerg   assert(curPool && "re-emitting in undelayed context not supported");
86947330f729Sjoerg   curPool->steal(pool);
86957330f729Sjoerg }
8696