gchatelet updated this revision to Diff 225575.
gchatelet marked 3 inline comments as done.
gchatelet added a comment.

- Change NoBuiltin from InheritableAttr to Attr
- Improve tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68028/new/

https://reviews.llvm.org/D68028

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/no-builtin.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/Sema/no-builtin.cpp

Index: clang/test/Sema/no-builtin.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/no-builtin.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+
+/// Prevent use of all builtins.
+void valid_attribute_all_1() __attribute__((no_builtin)) {}
+void valid_attribute_all_2() __attribute__((no_builtin())) {}
+
+/// Prevent use of specific builtins.
+void valid_attribute_function() __attribute__((no_builtin("memcpy"))) {}
+void valid_attribute_functions() __attribute__((no_builtin("memcpy"))) __attribute__((no_builtin("memcmp"))) {}
+
+/// Many times the same builtin is fine.
+void many_attribute_function_1() __attribute__((no_builtin)) __attribute__((no_builtin)) {}
+void many_attribute_function_2() __attribute__((no_builtin("memcpy"))) __attribute__((no_builtin("memcpy"))) {}
+void many_attribute_function_3() __attribute__((no_builtin("memcpy", "memcpy"))) {}
+void many_attribute_function_4() __attribute__((no_builtin("memcpy", "memcpy"))) __attribute__((no_builtin("memcpy"))) {}
+
+/// Invalid builtin name.
+void invalid_builtin() __attribute__((no_builtin("not_a_builtin"))) {}
+// expected-warning@-1 {{'not_a_builtin' is not a valid builtin name for no_builtin}}
+
+/// Can't use bare no_builtin with a named one.
+void wildcard_and_functionname() __attribute__((no_builtin)) __attribute__((no_builtin("memcpy"))) {}
+// expected-error@-1 {{empty no_builtin cannot be composed with named ones}}
+
+/// Can't attach attribute to a variable.
+int __attribute__((no_builtin)) variable;
+// expected-warning@-1 {{'no_builtin' attribute only applies to functions}}
+
+/// Can't attach attribute to a declaration.
+void nobuiltin_on_declaration() __attribute__((no_builtin));
+// expected-error@-1 {{no_builtin attribute is permitted on definitions only}}
+
+struct S {
+  /// Can't attach attribute to a defaulted function,
+  S()
+  __attribute__((no_builtin)) = default;
+  // expected-error@-1 {{no_builtin attribute has no effect on defaulted or deleted functions}}
+
+  /// Can't attach attribute to a deleted function,
+  S(const S &)
+  __attribute__((no_builtin)) = delete;
+  // expected-error@-1 {{no_builtin attribute has no effect on defaulted or deleted functions}}
+};
+
+/// Can't attach attribute to an aliased function.
+void alised_function() {}
+void aliasing_function() __attribute__((no_builtin)) __attribute__((alias("alised_function")));
+// expected-error@-1 {{no_builtin attribute is permitted on definitions only}}
\ No newline at end of file
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -74,6 +74,7 @@
 // CHECK-NEXT: NSConsumed (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: NSConsumesSelf (SubjectMatchRule_objc_method)
 // CHECK-NEXT: Naked (SubjectMatchRule_function)
+// CHECK-NEXT: NoBuiltin (SubjectMatchRule_function)
 // CHECK-NEXT: NoCommon (SubjectMatchRule_variable)
 // CHECK-NEXT: NoDebug (SubjectMatchRule_type_alias, SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter)
 // CHECK-NEXT: NoDestroy (SubjectMatchRule_variable)
Index: clang/test/CodeGen/no-builtin.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/no-builtin.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define void @foo_no_mempcy() #0
+extern "C" void foo_no_mempcy() __attribute__((no_builtin("memcpy"))) {}
+
+// CHECK-LABEL: define void @foo_no_mempcy_twice() #0
+extern "C" void foo_no_mempcy_twice() __attribute__((no_builtin("memcpy"))) __attribute__((no_builtin("memcpy"))) {}
+
+// CHECK-LABEL: define void @foo_no_builtins() #1
+extern "C" void foo_no_builtins() __attribute__((no_builtin)) {}
+
+// CHECK-LABEL: define void @foo_no_mempcy_memset() #2
+extern "C" void foo_no_mempcy_memset() __attribute__((no_builtin("memset", "memcpy"))) {}
+
+// CHECK-LABEL: define void @separate_attrs() #2
+extern "C" void separate_attrs() __attribute__((no_builtin("memset"))) __attribute__((no_builtin("memcpy"))) {}
+
+// CHECK-LABEL: define void @separate_attrs_ordering() #2
+extern "C" void separate_attrs_ordering() __attribute__((no_builtin("memcpy"))) __attribute__((no_builtin("memset"))) {}
+
+struct A {
+  virtual int foo() const __attribute__((no_builtin("memcpy"))) { return 1; }
+  virtual ~A();
+};
+
+struct B : public A {
+  int foo() const override __attribute__((no_builtin("memmove"))) { return 2; }
+  virtual ~B();
+};
+
+// CHECK-LABEL: define void @call_a_foo(%struct.A* %a) #3
+extern "C" void call_a_foo(A *a) {
+  // CHECK: %call = call i32 %2(%struct.A* %0) #6
+  a->foo();
+}
+
+// CHECK-LABEL: define void @call_b_foo(%struct.B* %b) #3
+extern "C" void call_b_foo(B *b) {
+  // CHECK: %call = call i32 %2(%struct.B* %0) #7
+  b->foo();
+}
+
+A::~A() {} // Anchoring A so A::foo() gets generated
+B::~B() {} // Anchoring B so B::foo() gets generated
+
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK1A3fooEv(%struct.A* %this) unnamed_addr #0 comdat align 2
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK1B3fooEv(%struct.B* %this) unnamed_addr #5 comdat align 2
+
+// CHECK: attributes #0 = {{{.*}}"no-builtin-memcpy"{{.*}}}
+// CHECK: attributes #1 = {{{.*}}"no-builtins"{{.*}}}
+// CHECK: attributes #2 = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
+// CHECK: attributes #5 = {{{.*}}"no-builtin-memmove"{{.*}}}
+// CHECK: attributes #6 = { "no-builtin-memcpy" }
+// CHECK: attributes #7 = { "no-builtin-memmove" }
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -40,11 +40,7 @@
 using namespace sema;
 
 namespace AttributeLangSupport {
-  enum LANG {
-    C,
-    Cpp,
-    ObjC
-  };
+enum LANG { C, Cpp, ObjC };
 } // end namespace AttributeLangSupport
 
 //===----------------------------------------------------------------------===//
@@ -68,8 +64,8 @@
 /// been processed by Sema::GetTypeForDeclarator.
 static bool hasDeclarator(const Decl *D) {
   // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
-  return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) ||
-         isa<ObjCPropertyDecl>(D);
+  return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) ||
+         isa<TypedefNameDecl>(D) || isa<ObjCPropertyDecl>(D);
 }
 
 /// hasFunctionProto - Return true if the given decl has a argument
@@ -155,7 +151,7 @@
   if (!Cls)
     return false;
 
-  IdentifierInfo* ClsName = Cls->getIdentifier();
+  IdentifierInfo *ClsName = Cls->getIdentifier();
 
   // FIXME: Should we walk the chain of classes?
   return ClsName == &Ctx.Idents.get("NSString") ||
@@ -207,9 +203,8 @@
 /// output an error.
 static bool checkAttributeAtLeastNumArgs(Sema &S, const ParsedAttr &AL,
                                          unsigned Num) {
-  return checkAttributeNumArgsImpl(S, AL, Num,
-                                   diag::err_attribute_too_few_arguments,
-                                   std::less<unsigned>());
+  return checkAttributeNumArgsImpl(
+      S, AL, Num, diag::err_attribute_too_few_arguments, std::less<unsigned>());
 }
 
 /// Check if the attribute has at most as many args as Num. May
@@ -273,8 +268,9 @@
 /// that the result will fit into a regular (signed) int. All args have the same
 /// purpose as they do in checkUInt32Argument.
 template <typename AttrInfo>
-static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr,
-                                     int &Val, unsigned Idx = UINT_MAX) {
+static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI,
+                                     const Expr *Expr, int &Val,
+                                     unsigned Idx = UINT_MAX) {
   uint32_t UVal;
   if (!checkUInt32Argument(S, AI, Expr, UVal, Idx))
     return false;
@@ -306,8 +302,8 @@
 template <typename AttrTy>
 static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) {
   if (const auto *A = D->getAttr<AttrTy>()) {
-    S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL
-                                                                      << A;
+    S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible)
+        << &AL << A;
     S.Diag(A->getLocation(), diag::note_conflicting_attribute);
     return true;
   }
@@ -404,13 +400,13 @@
 }
 
 template <typename... DiagnosticArgs>
-static const Sema::SemaDiagnosticBuilder&
+static const Sema::SemaDiagnosticBuilder &
 appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) {
   return Bldr;
 }
 
 template <typename T, typename... DiagnosticArgs>
-static const Sema::SemaDiagnosticBuilder&
+static const Sema::SemaDiagnosticBuilder &
 appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
                   DiagnosticArgs &&... ExtraArgs) {
   return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
@@ -458,10 +454,9 @@
   return QT->isBooleanType() || QT->isIntegerType();
 }
 
-
 // Check to see if the type is a smart pointer of some kind.  We assume
 // it's a smart pointer if it defines both operator-> and operator*.
-static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
+static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType *RT) {
   auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record,
                                           OverloadedOperatorKind Op) {
     DeclContextLookupResult Result =
@@ -688,10 +683,10 @@
     const RecordType *RT = getRecordType(ArgTy);
 
     // Now check if we index into a record type function param.
-    if(!RT && ParamIdxOk) {
+    if (!RT && ParamIdxOk) {
       const auto *FD = dyn_cast<FunctionDecl>(D);
       const auto *IL = dyn_cast<IntegerLiteral>(ArgExp);
-      if(FD && IL) {
+      if (FD && IL) {
         unsigned int NumParams = FD->getNumParams();
         llvm::APInt ArgValue = IL->getValue();
         uint64_t ParamIdxFromOne = ArgValue.getZExtValue();
@@ -914,7 +909,7 @@
 
 static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
                                             const ParsedAttr &AL) {
-  SmallVector<Expr*, 2> Args;
+  SmallVector<Expr *, 2> Args;
   if (!checkTryLockFunAttrCommon(S, D, AL, Args))
     return;
 
@@ -924,7 +919,7 @@
 
 static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
                                                const ParsedAttr &AL) {
-  SmallVector<Expr*, 2> Args;
+  SmallVector<Expr *, 2> Args;
   if (!checkTryLockFunAttrCommon(S, D, AL, Args))
     return;
 
@@ -934,7 +929,7 @@
 
 static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   // check that the argument is lockable object
-  SmallVector<Expr*, 1> Args;
+  SmallVector<Expr *, 1> Args;
   checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
   unsigned Size = Args.size();
   if (Size == 0)
@@ -948,7 +943,7 @@
     return;
 
   // check that all arguments are lockable objects
-  SmallVector<Expr*, 1> Args;
+  SmallVector<Expr *, 1> Args;
   checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
   unsigned Size = Args.size();
   if (Size == 0)
@@ -1040,7 +1035,7 @@
     return true;
   }
 };
-}
+} // namespace
 
 static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if);
@@ -1068,6 +1063,56 @@
       S.Context, AL, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D)));
 }
 
+static void handleNoBuiltinAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  static constexpr const StringRef kWildcard = "*";
+
+  llvm::SmallVector<StringRef, 16> Names;
+  bool HasWildcard = false;
+
+  const auto AddBuiltinName = [&Names, &HasWildcard](StringRef Name) {
+    if (Name == kWildcard)
+      HasWildcard = true;
+    Names.push_back(Name);
+  };
+
+  // Add previously defined attributes.
+  if (const auto *NBA = D->getAttr<NoBuiltinAttr>())
+    for (StringRef BuiltinName : NBA->builtinNames())
+      AddBuiltinName(BuiltinName);
+
+  // Add current attributes.
+  if (AL.getNumArgs() == 0)
+    AddBuiltinName(kWildcard);
+  else
+    for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
+      StringRef BuiltinName;
+      SourceLocation LiteralLoc;
+      if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, &LiteralLoc))
+        return;
+
+      if (Builtin::Context::isBuiltinFunc(BuiltinName.data()))
+        AddBuiltinName(BuiltinName);
+      else
+        S.Diag(LiteralLoc, diag::warn_attribute_no_builtin_invalid_builtin_name)
+            << BuiltinName << AL.getAttrName()->getName();
+    }
+
+  // Repeating the same attribute is fine.
+  llvm::sort(Names);
+  Names.erase(std::unique(Names.begin(), Names.end()), Names.end());
+
+  // Empty no_builtin must be on its own.
+  if (HasWildcard && Names.size() > 1)
+    S.Diag(D->getLocation(),
+           diag::err_attribute_no_builtin_wildcard_or_builtin_name)
+        << AL.getAttrName()->getName();
+
+  if (D->hasAttr<NoBuiltinAttr>())
+    D->dropAttr<NoBuiltinAttr>();
+  D->addAttr(::new (S.Context)
+                 NoBuiltinAttr(S.Context, AL, Names.data(), Names.size()));
+}
+
 static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   if (D->hasAttr<PassObjectSizeAttr>()) {
     S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL;
@@ -1107,8 +1152,8 @@
     IdentifierLoc *IL = AL.getArgAsIdent(0);
     if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
                                                    DefaultState)) {
-      S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
-                                                               << IL->Ident;
+      S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
+          << AL << IL->Ident;
       return;
     }
   } else {
@@ -1126,8 +1171,8 @@
 
   if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
     if (!RD->hasAttr<ConsumableAttr>()) {
-      S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) <<
-        RD->getNameAsString();
+      S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class)
+          << RD->getNameAsString();
 
       return false;
     }
@@ -1193,10 +1238,10 @@
   // FIXME: This check is currently being done in the analysis.  It can be
   //        enabled here only after the parser propagates attributes at
   //        template specialization definition, not declaration.
-  //QualType ReturnType = cast<ParmVarDecl>(D)->getType();
-  //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
+  // QualType ReturnType = cast<ParmVarDecl>(D)->getType();
+  // const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
   //
-  //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
+  // if (!RD || !RD->hasAttr<ConsumableAttr>()) {
   //    S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
   //      ReturnType.getAsString();
   //    return;
@@ -1212,8 +1257,8 @@
     IdentifierLoc *IL = AL.getArgAsIdent(0);
     if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
                                                         ReturnState)) {
-      S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
-                                                               << IL->Ident;
+      S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
+          << AL << IL->Ident;
       return;
     }
   } else {
@@ -1225,9 +1270,9 @@
   // FIXME: This check is currently being done in the analysis.  It can be
   //        enabled here only after the parser propagates attributes at
   //        template specialization definition, not declaration.
-  //QualType ReturnType;
+  // QualType ReturnType;
   //
-  //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) {
+  // if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) {
   //  ReturnType = Param->getType();
   //
   //} else if (const CXXConstructorDecl *Constructor =
@@ -1239,9 +1284,9 @@
   //  ReturnType = cast<FunctionDecl>(D)->getCallResultType();
   //}
   //
-  //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
+  // const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
   //
-  //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
+  // if (!RD || !RD->hasAttr<ConsumableAttr>()) {
   //    S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
   //      ReturnType.getAsString();
   //    return;
@@ -1259,8 +1304,8 @@
     IdentifierLoc *Ident = AL.getArgAsIdent(0);
     StringRef Param = Ident->Ident->getName();
     if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) {
-      S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
-                                                                  << Param;
+      S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
+          << AL << Param;
       return;
     }
   } else {
@@ -1281,8 +1326,8 @@
     IdentifierLoc *Ident = AL.getArgAsIdent(0);
     StringRef Param = Ident->Ident->getName();
     if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) {
-      S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
-                                                                  << Param;
+      S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
+          << AL << Param;
       return;
     }
   } else {
@@ -1303,10 +1348,10 @@
   if (auto *TD = dyn_cast<TagDecl>(D))
     TD->addAttr(::new (S.Context) PackedAttr(S.Context, AL));
   else if (auto *FD = dyn_cast<FieldDecl>(D)) {
-    bool BitfieldByteAligned = (!FD->getType()->isDependentType() &&
-                                !FD->getType()->isIncompleteType() &&
-                                FD->isBitField() &&
-                                S.Context.getTypeAlign(FD->getType()) <= 8);
+    bool BitfieldByteAligned =
+        (!FD->getType()->isDependentType() &&
+         !FD->getType()->isIncompleteType() && FD->isBitField() &&
+         S.Context.getTypeAlign(FD->getType()) <= 8);
 
     if (S.getASTContext().getTargetInfo().getTriple().isPS4()) {
       if (BitfieldByteAligned)
@@ -1337,15 +1382,13 @@
           << AL << VD->getType() << 0;
       return false;
     }
-  }
-  else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
+  } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
     if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
       S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
           << AL << PD->getType() << 1;
       return false;
     }
-  }
-  else {
+  } else {
     S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL;
     return false;
   }
@@ -1394,9 +1437,10 @@
   // attributes. So, __attribute__((iboutletcollection(char))) will be
   // treated as __attribute__((iboutletcollection())).
   if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
-    S.Diag(AL.getLoc(),
-           QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype
-                               : diag::err_iboutletcollection_type) << QT;
+    S.Diag(AL.getLoc(), QT->isBuiltinType()
+                            ? diag::err_iboutletcollection_builtintype
+                            : diag::err_iboutletcollection_type)
+        << QT;
     return;
   }
 
@@ -1493,7 +1537,7 @@
       handleNonNullAttr(S, D, AL);
     } else {
       S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
-        << D->getSourceRange();
+          << D->getSourceRange();
     }
     return;
   }
@@ -1560,18 +1604,17 @@
     if (!E->isIntegerConstantExpr(I, Context)) {
       if (OE)
         Diag(AttrLoc, diag::err_attribute_argument_n_type)
-          << &TmpAttr << 1 << AANT_ArgumentIntegerConstant
-          << E->getSourceRange();
+            << &TmpAttr << 1 << AANT_ArgumentIntegerConstant
+            << E->getSourceRange();
       else
         Diag(AttrLoc, diag::err_attribute_argument_type)
-          << &TmpAttr << AANT_ArgumentIntegerConstant
-          << E->getSourceRange();
+            << &TmpAttr << AANT_ArgumentIntegerConstant << E->getSourceRange();
       return;
     }
 
     if (!I.isPowerOf2()) {
       Diag(AttrLoc, diag::err_alignment_not_power_of_two)
-        << E->getSourceRange();
+          << E->getSourceRange();
       return;
     }
   }
@@ -1581,8 +1624,8 @@
       llvm::APSInt I(64);
       if (!OE->isIntegerConstantExpr(I, Context)) {
         Diag(AttrLoc, diag::err_attribute_argument_n_type)
-          << &TmpAttr << 2 << AANT_ArgumentIntegerConstant
-          << OE->getSourceRange();
+            << &TmpAttr << 2 << AANT_ArgumentIntegerConstant
+            << OE->getSourceRange();
         return;
       }
     }
@@ -1685,21 +1728,21 @@
 
     // Is the function argument a pointer type?
     QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex());
-    int Err = -1;  // No error
+    int Err = -1; // No error
     switch (K) {
-      case OwnershipAttr::Takes:
-      case OwnershipAttr::Holds:
-        if (!T->isAnyPointerType() && !T->isBlockPointerType())
-          Err = 0;
-        break;
-      case OwnershipAttr::Returns:
-        if (!T->isIntegerType())
-          Err = 1;
-        break;
+    case OwnershipAttr::Takes:
+    case OwnershipAttr::Holds:
+      if (!T->isAnyPointerType() && !T->isBlockPointerType())
+        Err = 0;
+      break;
+    case OwnershipAttr::Returns:
+      if (!T->isIntegerType())
+        Err = 1;
+      break;
     }
     if (-1 != Err) {
-      S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err
-                                                    << Ex->getSourceRange();
+      S.Diag(AL.getLoc(), diag::err_ownership_type)
+          << AL << Err << Ex->getSourceRange();
       return;
     }
 
@@ -1707,8 +1750,8 @@
     for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
       // Cannot have two ownership attributes of different kinds for the same
       // index.
-      if (I->getOwnKind() != K && I->args_end() !=
-          std::find(I->args_begin(), I->args_end(), Idx)) {
+      if (I->getOwnKind() != K &&
+          I->args_end() != std::find(I->args_begin(), I->args_end(), Idx)) {
         S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I;
         return;
       } else if (K == OwnershipAttr::Returns &&
@@ -1857,8 +1900,8 @@
     return;
 
   // Check that the value.
-  if (Model != "global-dynamic" && Model != "local-dynamic"
-      && Model != "initial-exec" && Model != "local-exec") {
+  if (Model != "global-dynamic" && Model != "local-dynamic" &&
+      Model != "initial-exec" && Model != "local-exec") {
     S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg);
     return;
   }
@@ -1957,7 +2000,8 @@
 }
 
 static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
-  if (hasDeclarator(D)) return;
+  if (hasDeclarator(D))
+    return;
 
   if (!isa<ObjCMethodDecl>(D)) {
     S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
@@ -2075,8 +2119,7 @@
     // [[carries_dependency]] can only be applied to a parameter if it is a
     // parameter of a function declaration or lambda.
     if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) {
-      S.Diag(AL.getLoc(),
-             diag::err_carries_dependency_param_not_function_decl);
+      S.Diag(AL.getLoc(), diag::err_carries_dependency_param_not_function_decl);
       return;
     }
   }
@@ -2139,8 +2182,8 @@
                                   VersionTuple Introduced,
                                   VersionTuple Deprecated,
                                   VersionTuple Obsoleted) {
-  StringRef PlatformName
-    = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
+  StringRef PlatformName =
+      AvailabilityAttr::getPrettyPlatformName(Platform->getName());
   if (PlatformName.empty())
     PlatformName = Platform->getName();
 
@@ -2149,24 +2192,22 @@
   if (!Introduced.empty() && !Deprecated.empty() &&
       !(Introduced <= Deprecated)) {
     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
-      << 1 << PlatformName << Deprecated.getAsString()
-      << 0 << Introduced.getAsString();
+        << 1 << PlatformName << Deprecated.getAsString() << 0
+        << Introduced.getAsString();
     return true;
   }
 
-  if (!Introduced.empty() && !Obsoleted.empty() &&
-      !(Introduced <= Obsoleted)) {
+  if (!Introduced.empty() && !Obsoleted.empty() && !(Introduced <= Obsoleted)) {
     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
-      << 2 << PlatformName << Obsoleted.getAsString()
-      << 0 << Introduced.getAsString();
+        << 2 << PlatformName << Obsoleted.getAsString() << 0
+        << Introduced.getAsString();
     return true;
   }
 
-  if (!Deprecated.empty() && !Obsoleted.empty() &&
-      !(Deprecated <= Obsoleted)) {
+  if (!Deprecated.empty() && !Obsoleted.empty() && !(Deprecated <= Obsoleted)) {
     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
-      << 2 << PlatformName << Obsoleted.getAsString()
-      << 1 << Deprecated.getAsString();
+        << 2 << PlatformName << Obsoleted.getAsString() << 1
+        << Deprecated.getAsString();
     return true;
   }
 
@@ -2263,7 +2304,8 @@
             Which = 0;
             FirstVersion = OldIntroduced;
             SecondVersion = Introduced;
-          } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) {
+          } else if (!versionsMatch(Deprecated, OldDeprecated,
+                                    OverrideOrImpl)) {
             Which = 1;
             FirstVersion = Deprecated;
             SecondVersion = OldDeprecated;
@@ -2276,15 +2318,15 @@
           if (Which == -1) {
             Diag(OldAA->getLocation(),
                  diag::warn_mismatched_availability_override_unavail)
-              << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
-              << (AMK == AMK_Override);
+                << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
+                << (AMK == AMK_Override);
           } else {
             Diag(OldAA->getLocation(),
                  diag::warn_mismatched_availability_override)
-              << Which
-              << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
-              << FirstVersion.getAsString() << SecondVersion.getAsString()
-              << (AMK == AMK_Override);
+                << Which
+                << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
+                << FirstVersion.getAsString() << SecondVersion.getAsString()
+                << (AMK == AMK_Override);
           }
           if (AMK == AMK_Override)
             Diag(CI.getLoc(), diag::note_overridden_method);
@@ -2326,10 +2368,8 @@
     }
   }
 
-  if (FoundAny &&
-      MergedIntroduced == Introduced &&
-      MergedDeprecated == Deprecated &&
-      MergedObsoleted == Obsoleted)
+  if (FoundAny && MergedIntroduced == Introduced &&
+      MergedDeprecated == Deprecated && MergedObsoleted == Obsoleted)
     return nullptr;
 
   // Only create a new attribute if !OverrideOrImpl, but we want to do
@@ -2354,7 +2394,7 @@
   IdentifierInfo *II = Platform->Ident;
   if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
     S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
-      << Platform->Ident;
+        << Platform->Ident;
 
   auto *ND = dyn_cast<NamedDecl>(D);
   if (!ND) // We warned about this already, so just return.
@@ -2401,37 +2441,37 @@
       NewII = &S.Context.Idents.get("watchos_app_extension");
 
     if (NewII) {
-        auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple {
-          if (Version.empty())
-            return Version;
-          auto Major = Version.getMajor();
-          auto NewMajor = Major >= 9 ? Major - 7 : 0;
-          if (NewMajor >= 2) {
-            if (Version.getMinor().hasValue()) {
-              if (Version.getSubminor().hasValue())
-                return VersionTuple(NewMajor, Version.getMinor().getValue(),
-                                    Version.getSubminor().getValue());
-              else
-                return VersionTuple(NewMajor, Version.getMinor().getValue());
-            }
-            return VersionTuple(NewMajor);
+      auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple {
+        if (Version.empty())
+          return Version;
+        auto Major = Version.getMajor();
+        auto NewMajor = Major >= 9 ? Major - 7 : 0;
+        if (NewMajor >= 2) {
+          if (Version.getMinor().hasValue()) {
+            if (Version.getSubminor().hasValue())
+              return VersionTuple(NewMajor, Version.getMinor().getValue(),
+                                  Version.getSubminor().getValue());
+            else
+              return VersionTuple(NewMajor, Version.getMinor().getValue());
           }
+          return VersionTuple(NewMajor);
+        }
 
-          return VersionTuple(2, 0);
-        };
+        return VersionTuple(2, 0);
+      };
 
-        auto NewIntroduced = adjustWatchOSVersion(Introduced.Version);
-        auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version);
-        auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
-
-        AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
-            ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
-            NewObsoleted, IsUnavailable, Str, IsStrict, Replacement,
-            Sema::AMK_None,
-            PriorityModifier + Sema::AP_InferredFromOtherPlatform);
-        if (NewAttr)
-          D->addAttr(NewAttr);
-      }
+      auto NewIntroduced = adjustWatchOSVersion(Introduced.Version);
+      auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version);
+      auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
+
+      AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
+          ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
+          NewObsoleted, IsUnavailable, Str, IsStrict, Replacement,
+          Sema::AMK_None,
+          PriorityModifier + Sema::AP_InferredFromOtherPlatform);
+      if (NewAttr)
+        D->addAttr(NewAttr);
+    }
   } else if (S.Context.getTargetInfo().getTriple().isTvOS()) {
     // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning
     // matches before the start of the tvOS platform.
@@ -2449,7 +2489,7 @@
           PriorityModifier + Sema::AP_InferredFromOtherPlatform);
       if (NewAttr)
         D->addAttr(NewAttr);
-      }
+    }
   }
 }
 
@@ -2508,10 +2548,8 @@
   }
 
   // 'type_visibility' can only go on a type or namespace.
-  if (isTypeVisibility &&
-      !(isa<TagDecl>(D) ||
-        isa<ObjCInterfaceDecl>(D) ||
-        isa<NamespaceDecl>(D))) {
+  if (isTypeVisibility && !(isa<TagDecl>(D) || isa<ObjCInterfaceDecl>(D) ||
+                            isa<NamespaceDecl>(D))) {
     S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
         << AL << ExpectedTypeOrNamespace;
     return;
@@ -2525,8 +2563,8 @@
 
   VisibilityAttr::VisibilityType type;
   if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
-    S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL
-                                                                << TypeStr;
+    S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
+        << AL << TypeStr;
     return;
   }
 
@@ -2582,15 +2620,13 @@
       S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
       return;
     }
-  }
-  else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
+  } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
     QualType T = PD->getType();
     if (!T->isCARCBridgableType()) {
       S.Diag(PD->getLocation(), diag::err_nsobject_attribute);
       return;
     }
-  }
-  else {
+  } else {
     // It is okay to include this attribute on properties, e.g.:
     //
     //  @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
@@ -2647,7 +2683,7 @@
 
     if (Idx.isSigned() && Idx.isNegative()) {
       S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero)
-        << E->getSourceRange();
+          << E->getSourceRange();
       return;
     }
 
@@ -2670,7 +2706,7 @@
       // FIXME: This error message could be improved, it would be nice
       // to say what the bounds actually are.
       S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
-        << E->getSourceRange();
+          << E->getSourceRange();
       return;
     }
   }
@@ -2700,8 +2736,10 @@
     QualType Ty = V->getType();
     if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
       const FunctionType *FT = Ty->isFunctionPointerType()
-       ? D->getFunctionType()
-       : Ty->castAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
+                                   ? D->getFunctionType()
+                                   : Ty->castAs<BlockPointerType>()
+                                         ->getPointeeType()
+                                         ->getAs<FunctionType>();
       if (!cast<FunctionProtoType>(FT)->isVariadic()) {
         int m = Ty->isFunctionPointerType() ? 0 : 1;
         S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
@@ -2764,7 +2802,7 @@
   if (!D->canBeWeakImported(isDef)) {
     if (isDef)
       S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition)
-        << "weak_import";
+          << "weak_import";
     else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
              (S.Context.getTargetInfo().getTriple().isOSDarwin() &&
               (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
@@ -2796,9 +2834,9 @@
   }
 
   WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>();
-  if (Existing && !(Existing->getXDim() == WGSize[0] &&
-                    Existing->getYDim() == WGSize[1] &&
-                    Existing->getZDim() == WGSize[2]))
+  if (Existing &&
+      !(Existing->getXDim() == WGSize[0] && Existing->getYDim() == WGSize[1] &&
+        Existing->getZDim() == WGSize[2]))
     S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
 
   D->addAttr(::new (S.Context)
@@ -2866,7 +2904,7 @@
     if (ExistingAttr->getName() == Name)
       return nullptr;
     Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
-         << 1 /*section*/;
+        << 1 /*section*/;
     Diag(CI.getLoc(), diag::note_previous_attribute);
     return nullptr;
   }
@@ -2876,8 +2914,8 @@
 bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
   std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName);
   if (!Error.empty()) {
-    Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
-         << 1 /*'section'*/;
+    Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
+        << Error << 1 /*'section'*/;
     return false;
   }
   return true;
@@ -2897,8 +2935,7 @@
   // If the target wants to validate the section specifier, make it happen.
   std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);
   if (!Error.empty()) {
-    S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
-    << Error;
+    S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error;
     return;
   }
 
@@ -2934,7 +2971,7 @@
     if (ExistingAttr->getName() == Name)
       return nullptr;
     Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
-         << 0 /*codeseg*/;
+        << 0 /*codeseg*/;
     Diag(CI.getLoc(), diag::note_previous_attribute);
     return nullptr;
   }
@@ -2950,10 +2987,9 @@
     return;
   if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
     if (!ExistingAttr->isImplicit()) {
-      S.Diag(AL.getLoc(),
-             ExistingAttr->getName() == Str
-             ? diag::warn_duplicate_codeseg_attribute
-             : diag::err_conflicting_codeseg_attribute);
+      S.Diag(AL.getLoc(), ExistingAttr->getName() == Str
+                              ? diag::warn_duplicate_codeseg_attribute
+                              : diag::err_conflicting_codeseg_attribute);
       return;
     }
     D->dropAttr<CodeSegAttr>();
@@ -3035,8 +3071,8 @@
     FD = dyn_cast<FunctionDecl>(DRE->getDecl());
     NI = DRE->getNameInfo();
     if (!FD) {
-      S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1
-        << NI.getName();
+      S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function)
+          << 1 << NI.getName();
       return;
     }
   } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
@@ -3045,8 +3081,8 @@
     FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
     NI = ULE->getNameInfo();
     if (!FD) {
-      S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
-        << NI.getName();
+      S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function)
+          << 2 << NI.getName();
       if (ULE->getType() == S.Context.OverloadTy)
         S.NoteAllOverloadCandidates(ULE);
       return;
@@ -3058,7 +3094,7 @@
 
   if (FD->getNumParams() != 1) {
     S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
-      << NI.getName();
+        << NI.getName();
     return;
   }
 
@@ -3066,10 +3102,10 @@
   // If this ever proves to be a problem it should be easy to fix.
   QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType());
   QualType ParamTy = FD->getParamDecl(0)->getType();
-  if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
-                                   ParamTy, Ty) != Sema::Compatible) {
+  if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), ParamTy,
+                                   Ty) != Sema::Compatible) {
     S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type)
-      << NI.getName() << ParamTy << Ty;
+        << NI.getName() << ParamTy << Ty;
     return;
   }
 
@@ -3108,8 +3144,7 @@
   QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
 
   bool NotNSStringTy = !isNSStringType(Ty, S.Context);
-  if (NotNSStringTy &&
-      !isCFStringType(Ty, S.Context) &&
+  if (NotNSStringTy && !isCFStringType(Ty, S.Context) &&
       (!Ty->isPointerType() ||
        !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) {
     S.Diag(AL.getLoc(), diag::err_format_attribute_not)
@@ -3118,8 +3153,7 @@
     return;
   }
   Ty = getFunctionOrMethodResultType(D);
-  if (!isNSStringType(Ty, S.Context) &&
-      !isCFStringType(Ty, S.Context) &&
+  if (!isNSStringType(Ty, S.Context) && !isCFStringType(Ty, S.Context) &&
       (!Ty->isPointerType() ||
        !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) {
     S.Diag(AL.getLoc(), diag::err_format_attribute_result_not)
@@ -3204,8 +3238,7 @@
                                   int FirstArg) {
   // Check whether we already have an equivalent format attribute.
   for (auto *F : D->specific_attrs<FormatAttr>()) {
-    if (F->getType() == Format &&
-        F->getFormatIdx() == FormatIdx &&
+    if (F->getType() == Format && F->getFormatIdx() == FormatIdx &&
         F->getFirstArg() == FirstArg) {
       // If we don't have a valid location for this attribute, adopt the
       // location.
@@ -3271,7 +3304,7 @@
     if (ArgIdx == 0) {
       S.Diag(AL.getLoc(),
              diag::err_format_attribute_implicit_this_format_string)
-        << IdxExpr->getSourceRange();
+          << IdxExpr->getSourceRange();
       return;
     }
     ArgIdx--;
@@ -3283,8 +3316,8 @@
   if (Kind == CFStringFormat) {
     if (!isCFStringType(Ty, S.Context)) {
       S.Diag(AL.getLoc(), diag::err_format_attribute_not)
-        << "a CFString" << IdxExpr->getSourceRange()
-        << getFunctionOrMethodParamRange(D, ArgIdx);
+          << "a CFString" << IdxExpr->getSourceRange()
+          << getFunctionOrMethodParamRange(D, ArgIdx);
       return;
     }
   } else if (Kind == NSStringFormat) {
@@ -3292,15 +3325,15 @@
     // semantics?
     if (!isNSStringType(Ty, S.Context)) {
       S.Diag(AL.getLoc(), diag::err_format_attribute_not)
-        << "an NSString" << IdxExpr->getSourceRange()
-        << getFunctionOrMethodParamRange(D, ArgIdx);
+          << "an NSString" << IdxExpr->getSourceRange()
+          << getFunctionOrMethodParamRange(D, ArgIdx);
       return;
     }
   } else if (!Ty->isPointerType() ||
              !Ty->castAs<PointerType>()->getPointeeType()->isCharType()) {
     S.Diag(AL.getLoc(), diag::err_format_attribute_not)
-      << "a string type" << IdxExpr->getSourceRange()
-      << getFunctionOrMethodParamRange(D, ArgIdx);
+        << "a string type" << IdxExpr->getSourceRange()
+        << getFunctionOrMethodParamRange(D, ArgIdx);
     return;
   }
 
@@ -3325,10 +3358,10 @@
   if (Kind == StrftimeFormat) {
     if (FirstArg != 0) {
       S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter)
-        << FirstArgExpr->getSourceRange();
+          << FirstArgExpr->getSourceRange();
       return;
     }
-  // if 0 it disables parameter checking (to use with e.g. va_list)
+    // if 0 it disables parameter checking (to use with e.g. va_list)
   } else if (FirstArg != 0 && FirstArg != NumArgs) {
     S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
         << AL << 3 << FirstArgExpr->getSourceRange();
@@ -3489,8 +3522,8 @@
     RD = dyn_cast<RecordDecl>(D);
 
   if (!RD || !RD->isUnion()) {
-    S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL
-                                                              << ExpectedUnion;
+    S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << AL << ExpectedUnion;
     return;
   }
 
@@ -3502,7 +3535,7 @@
   }
 
   RecordDecl::field_iterator Field = RD->field_begin(),
-                          FieldEnd = RD->field_end();
+                             FieldEnd = RD->field_end();
   if (Field == FieldEnd) {
     S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
     return;
@@ -3513,7 +3546,7 @@
   if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
     S.Diag(FirstField->getLocation(),
            diag::warn_transparent_union_attribute_floating)
-      << FirstType->isVectorType() << FirstType;
+        << FirstType->isVectorType() << FirstType;
     return;
   }
 
@@ -3534,15 +3567,15 @@
         S.Context.getTypeAlign(FieldType) > FirstAlign) {
       // Warn if we drop the attribute.
       bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
-      unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
-                                 : S.Context.getTypeAlign(FieldType);
+      unsigned FieldBits = isSize ? S.Context.getTypeSize(FieldType)
+                                  : S.Context.getTypeAlign(FieldType);
       S.Diag(Field->getLocation(),
-          diag::warn_transparent_union_attribute_field_size_align)
-        << isSize << Field->getDeclName() << FieldBits;
-      unsigned FirstBits = isSize? FirstSize : FirstAlign;
+             diag::warn_transparent_union_attribute_field_size_align)
+          << isSize << Field->getDeclName() << FieldBits;
+      unsigned FirstBits = isSize ? FirstSize : FirstAlign;
       S.Diag(FirstField->getLocation(),
              diag::note_transparent_union_first_field_size_align)
-        << isSize << FirstBits;
+          << isSize << FirstBits;
       return;
     }
   }
@@ -3585,22 +3618,21 @@
   if (!T->isDependentType() && !T->isAnyPointerType() &&
       !T->isReferenceType() && !T->isMemberPointerType()) {
     Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only)
-      << &TmpAttr /*TmpAttr.getName()*/ << T << D->getSourceRange();
+        << &TmpAttr /*TmpAttr.getName()*/ << T << D->getSourceRange();
     return;
   }
 
   if (!E->isValueDependent()) {
     llvm::APSInt Alignment;
-    ExprResult ICE
-      = VerifyIntegerConstantExpression(E, &Alignment,
-          diag::err_align_value_attribute_argument_not_int,
-            /*AllowFold*/ false);
+    ExprResult ICE = VerifyIntegerConstantExpression(
+        E, &Alignment, diag::err_align_value_attribute_argument_not_int,
+        /*AllowFold*/ false);
     if (ICE.isInvalid())
       return;
 
     if (!Alignment.isPowerOf2()) {
       Diag(AttrLoc, diag::err_alignment_not_power_of_two)
-        << E->getSourceRange();
+          << E->getSourceRange();
       return;
     }
 
@@ -3667,14 +3699,15 @@
       if (FD->isBitField())
         DiagKind = 3;
     } else if (!isa<TagDecl>(D)) {
-      Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
-        << (TmpAttr.isC11() ? ExpectedVariableOrField
-                            : ExpectedVariableFieldOrTag);
+      Diag(AttrLoc, diag::err_attribute_wrong_decl_type)
+          << &TmpAttr
+          << (TmpAttr.isC11() ? ExpectedVariableOrField
+                              : ExpectedVariableFieldOrTag);
       return;
     }
     if (DiagKind != -1) {
       Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type)
-        << &TmpAttr << DiagKind;
+          << &TmpAttr << DiagKind;
       return;
     }
   }
@@ -3700,10 +3733,9 @@
 
   // FIXME: Cache the number on the AL object?
   llvm::APSInt Alignment;
-  ExprResult ICE
-    = VerifyIntegerConstantExpression(E, &Alignment,
-        diag::err_aligned_attribute_argument_not_int,
-        /*AllowFold*/ false);
+  ExprResult ICE = VerifyIntegerConstantExpression(
+      E, &Alignment, diag::err_aligned_attribute_argument_not_int,
+      /*AllowFold*/ false);
   if (ICE.isInvalid())
     return;
 
@@ -3717,7 +3749,7 @@
   if (!(TmpAttr.isAlignas() && !Alignment)) {
     if (!llvm::isPowerOf2_64(AlignVal)) {
       Diag(AttrLoc, diag::err_alignment_not_power_of_two)
-        << E->getSourceRange();
+          << E->getSourceRange();
       return;
     }
   }
@@ -3727,8 +3759,8 @@
       Context.getTargetInfo().getTriple().isOSBinFormatCOFF() ? 8192
                                                               : 268435456;
   if (AlignVal > MaxValidAlignment) {
-    Diag(AttrLoc, diag::err_attribute_aligned_too_great) << MaxValidAlignment
-                                                         << E->getSourceRange();
+    Diag(AttrLoc, diag::err_attribute_aligned_too_great)
+        << MaxValidAlignment << E->getSourceRange();
     return;
   }
 
@@ -3792,7 +3824,7 @@
     CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy);
     if (NaturalAlign > RequestedAlign)
       Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned)
-        << DiagTy << (unsigned)NaturalAlign.getQuantity();
+          << DiagTy << (unsigned)NaturalAlign.getQuantity();
   }
 }
 
@@ -4081,8 +4113,9 @@
     // ImplicitParm or VarTemplateSpecialization).
     if (VD->getKind() != Decl::Var) {
       Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
-          << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
-                                            : ExpectedVariableOrFunction);
+          << AL
+          << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
+                                      : ExpectedVariableOrFunction);
       return nullptr;
     }
     // Attribute does not apply to non-static local variables.
@@ -4104,8 +4137,9 @@
     // ImplicitParm or VarTemplateSpecialization).
     if (VD->getKind() != Decl::Var) {
       Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type)
-          << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
-                                             : ExpectedVariableOrFunction);
+          << &AL
+          << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
+                                      : ExpectedVariableOrFunction);
       return nullptr;
     }
     // Attribute does not apply to non-static local variables.
@@ -4262,12 +4296,13 @@
 }
 
 static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
-  if (hasDeclarator(D)) return;
+  if (hasDeclarator(D))
+    return;
 
   // Diagnostic is emitted elsewhere: here we store the (valid) AL
   // in the Decl node for syntactic reasoning, e.g., pretty-printing.
   CallingConv CC;
-  if (S.CheckCallingConvAttr(AL, CC, /*FD*/nullptr))
+  if (S.CheckCallingConvAttr(AL, CC, /*FD*/ nullptr))
     return;
 
   if (!isa<ObjCMethodDecl>(D)) {
@@ -4428,7 +4463,7 @@
     return true;
 
   if (Attrs.hasProcessingCache()) {
-    CC = (CallingConv) Attrs.getProcessingCache();
+    CC = (CallingConv)Attrs.getProcessingCache();
     return false;
   }
 
@@ -4468,12 +4503,11 @@
     CC = CC_X86RegCall;
     break;
   case ParsedAttr::AT_MSABI:
-    CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
-                                                             CC_Win64;
+    CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : CC_Win64;
     break;
   case ParsedAttr::AT_SysVABI:
-    CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
-                                                             CC_C;
+    CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV
+                                                           : CC_C;
     break;
   case ParsedAttr::AT_Pcs: {
     StringRef StrRef;
@@ -4502,7 +4536,8 @@
   case ParsedAttr::AT_PreserveAll:
     CC = CC_PreserveAll;
     break;
-  default: llvm_unreachable("unexpected attribute kind");
+  default:
+    llvm_unreachable("unexpected attribute kind");
   }
 
   TargetInfo::CallingConvCheckResult A = TargetInfo::CCCR_OK;
@@ -4573,7 +4608,7 @@
   }
   }
 
-  Attrs.setProcessingCache((unsigned) CC);
+  Attrs.setProcessingCache((unsigned)CC);
   return false;
 }
 
@@ -4675,7 +4710,7 @@
 
   if (Context.getTargetInfo().getRegParmMax() == 0) {
     Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform)
-      << NumParamsExpr->getSourceRange();
+        << NumParamsExpr->getSourceRange();
     AL.setInvalid();
     return true;
   }
@@ -4683,7 +4718,8 @@
   numParams = NP;
   if (numParams > Context.getTargetInfo().getRegParmMax()) {
     Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number)
-      << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
+        << Context.getTargetInfo().getRegParmMax()
+        << NumParamsExpr->getSourceRange();
     AL.setInvalid();
     return true;
   }
@@ -4714,8 +4750,8 @@
   }
   // Make sure we can fit it in 32 bits.
   if (!I.isIntN(32)) {
-    S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false)
-                                                     << 32 << /* Unsigned */ 1;
+    S.Diag(E->getExprLoc(), diag::err_ice_too_large)
+        << I.toString(10, false) << 32 << /* Unsigned */ 1;
     return nullptr;
   }
   if (I < 0)
@@ -4949,8 +4985,8 @@
     // Attributes on parameters are used for out-parameters,
     // passed as pointers-to-pointers.
     unsigned DiagID = K == Sema::RetainOwnershipKind::CF
-            ? /*pointer-to-CF-pointer*/2
-            : /*pointer-to-OSObject-pointer*/3;
+                          ? /*pointer-to-CF-pointer*/ 2
+                          : /*pointer-to-OSObject-pointer*/ 3;
     ReturnType = Param->getType()->getPointeeType();
     if (ReturnType.isNull()) {
       S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
@@ -4962,7 +4998,8 @@
   } else {
     AttributeDeclKind ExpectedDeclKind;
     switch (AL.getKind()) {
-    default: llvm_unreachable("invalid ownership attribute");
+    default:
+      llvm_unreachable("invalid ownership attribute");
     case ParsedAttr::AT_NSReturnsRetained:
     case ParsedAttr::AT_NSReturnsAutoreleased:
     case ParsedAttr::AT_NSReturnsNotRetained:
@@ -4985,7 +5022,8 @@
   bool Cf;
   unsigned ParmDiagID = 2; // Pointer-to-CF-pointer
   switch (AL.getKind()) {
-  default: llvm_unreachable("invalid ownership attribute");
+  default:
+    llvm_unreachable("invalid ownership attribute");
   case ParsedAttr::AT_NSReturnsRetained:
     TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);
     Cf = false;
@@ -5020,11 +5058,7 @@
           << AL << ParmDiagID << AL.getRange();
     } else {
       // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
-      enum : unsigned {
-        Function,
-        Method,
-        Property
-      } SubjectKind = Function;
+      enum : unsigned { Function, Method, Property } SubjectKind = Function;
       if (isa<ObjCMethodDecl>(D))
         SubjectKind = Method;
       else if (isa<ObjCPropertyDecl>(D))
@@ -5036,29 +5070,29 @@
   }
 
   switch (AL.getKind()) {
-    default:
-      llvm_unreachable("invalid ownership attribute");
-    case ParsedAttr::AT_NSReturnsAutoreleased:
-      handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL);
-      return;
-    case ParsedAttr::AT_CFReturnsNotRetained:
-      handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL);
-      return;
-    case ParsedAttr::AT_NSReturnsNotRetained:
-      handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL);
-      return;
-    case ParsedAttr::AT_CFReturnsRetained:
-      handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL);
-      return;
-    case ParsedAttr::AT_NSReturnsRetained:
-      handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL);
-      return;
-    case ParsedAttr::AT_OSReturnsRetained:
-      handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL);
-      return;
-    case ParsedAttr::AT_OSReturnsNotRetained:
-      handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL);
-      return;
+  default:
+    llvm_unreachable("invalid ownership attribute");
+  case ParsedAttr::AT_NSReturnsAutoreleased:
+    handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL);
+    return;
+  case ParsedAttr::AT_CFReturnsNotRetained:
+    handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL);
+    return;
+  case ParsedAttr::AT_NSReturnsNotRetained:
+    handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL);
+    return;
+  case ParsedAttr::AT_CFReturnsRetained:
+    handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL);
+    return;
+  case ParsedAttr::AT_NSReturnsRetained:
+    handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL);
+    return;
+  case ParsedAttr::AT_OSReturnsRetained:
+    handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL);
+    return;
+  case ParsedAttr::AT_OSReturnsNotRetained:
+    handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL);
+    return;
   };
 }
 
@@ -5094,14 +5128,14 @@
 
   const DeclContext *DC = Method->getDeclContext();
   if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
-    S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
-                                                                      << 0;
+    S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol)
+        << Attrs << 0;
     S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
     return;
   }
   if (Method->getMethodFamily() == OMF_dealloc) {
-    S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
-                                                                      << 1;
+    S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol)
+        << Attrs << 1;
     return;
   }
 
@@ -5156,9 +5190,9 @@
     return;
   }
   IdentifierInfo *ClassMethod =
-    AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
+      AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
   IdentifierInfo *InstanceMethod =
-    AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
+      AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
   D->addAttr(::new (S.Context) ObjCBridgeRelatedAttr(
       S.Context, AL, RelatedClass, ClassMethod, InstanceMethod));
 }
@@ -5224,7 +5258,8 @@
 }
 
 static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
-  if (hasDeclarator(D)) return;
+  if (hasDeclarator(D))
+    return;
 
   S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)
       << AL.getRange() << AL << ExpectedVariable;
@@ -5235,10 +5270,8 @@
   const auto *VD = cast<ValueDecl>(D);
   QualType QT = VD->getType();
 
-  if (!QT->isDependentType() &&
-      !QT->isObjCLifetimeType()) {
-    S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type)
-      << QT;
+  if (!QT->isDependentType() && !QT->isObjCLifetimeType()) {
+    S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type) << QT;
     return;
   }
 
@@ -5415,8 +5448,8 @@
 
   ARMInterruptAttr::InterruptType Kind;
   if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
-    S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
-                                                                 << ArgLoc;
+    S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+        << AL << Str << ArgLoc;
     return;
   }
 
@@ -5620,7 +5653,8 @@
   handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
 }
 
-static void handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+static void handleWebAssemblyImportModuleAttr(Sema &S, Decl *D,
+                                              const ParsedAttr &AL) {
   if (!isFunctionOrMethod(D)) {
     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
         << "'import_module'" << ExpectedFunction;
@@ -5642,7 +5676,8 @@
                   WebAssemblyImportModuleAttr(S.Context, AL, Str));
 }
 
-static void handleWebAssemblyImportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+static void handleWebAssemblyImportNameAttr(Sema &S, Decl *D,
+                                            const ParsedAttr &AL) {
   if (!isFunctionOrMethod(D)) {
     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
         << "'import_name'" << ExpectedFunction;
@@ -5663,12 +5698,11 @@
   FD->addAttr(::new (S.Context) WebAssemblyImportNameAttr(S.Context, AL, Str));
 }
 
-static void handleRISCVInterruptAttr(Sema &S, Decl *D,
-                                     const ParsedAttr &AL) {
+static void handleRISCVInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   // Warn about repeated attributes.
   if (const auto *A = D->getAttr<RISCVInterruptAttr>()) {
     S.Diag(AL.getRange().getBegin(),
-      diag::warn_riscv_repeated_interrupt_attribute);
+           diag::warn_riscv_repeated_interrupt_attribute);
     S.Diag(A->getLocation(), diag::note_riscv_repeated_interrupt_attribute);
     return;
   }
@@ -5695,26 +5729,26 @@
 
   if (D->getFunctionType() == nullptr) {
     S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
-      << "'interrupt'" << ExpectedFunction;
+        << "'interrupt'" << ExpectedFunction;
     return;
   }
 
   if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
     S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
-      << /*RISC-V*/ 2 << 0;
+        << /*RISC-V*/ 2 << 0;
     return;
   }
 
   if (!getFunctionOrMethodResultType(D)->isVoidType()) {
     S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
-      << /*RISC-V*/ 2 << 1;
+        << /*RISC-V*/ 2 << 1;
     return;
   }
 
   RISCVInterruptAttr::InterruptType Kind;
   if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
-    S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
-                                                                 << ArgLoc;
+    S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+        << AL << Str << ArgLoc;
     return;
   }
 
@@ -5883,7 +5917,7 @@
   // Also don't warn on function pointer typedefs.
   const auto *TD = dyn_cast<TypedefNameDecl>(D);
   if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
-    TD->getUnderlyingType()->isFunctionType()))
+             TD->getUnderlyingType()->isFunctionType()))
     return;
   // Attribute can only be applied to function types.
   if (!isa<FunctionDecl>(D)) {
@@ -6033,7 +6067,7 @@
 }
 
 static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
-  SmallVector<Expr*, 1> Args;
+  SmallVector<Expr *, 1> Args;
   if (!checkLockFunAttrCommon(S, D, AL, Args))
     return;
 
@@ -6043,7 +6077,7 @@
 
 static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
                                         const ParsedAttr &AL) {
-  SmallVector<Expr*, 1> Args;
+  SmallVector<Expr *, 1> Args;
   if (!checkLockFunAttrCommon(S, D, AL, Args))
     return;
 
@@ -6053,7 +6087,7 @@
 
 static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
                                            const ParsedAttr &AL) {
-  SmallVector<Expr*, 2> Args;
+  SmallVector<Expr *, 2> Args;
   if (!checkTryLockFunAttrCommon(S, D, AL, Args))
     return;
 
@@ -6077,7 +6111,7 @@
     return;
 
   // check that all arguments are lockable objects
-  SmallVector<Expr*, 1> Args;
+  SmallVector<Expr *, 1> Args;
   checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
   if (Args.empty())
     return;
@@ -6191,8 +6225,8 @@
     S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
         << AL << "2.0" << 0;
   else
-    S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored) << AL
-                                                                   << "2.0";
+    S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
+        << AL << "2.0";
 }
 
 /// Handles semantic checking for features that are common to all attributes,
@@ -6256,11 +6290,10 @@
     }
   }
 
-  // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an
-  // image object can be read and written.
-  // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe
-  // object. Using the read_write (or __read_write) qualifier with the pipe
-  // qualifier is a compilation error.
+  // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that
+  // an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel
+  // cannot read from and write to the same pipe object. Using the read_write
+  // (or __read_write) qualifier with the pipe qualifier is a compilation error.
   if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
     const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
     if (AL.getAttrName()->getName().find("read_write") != StringRef::npos) {
@@ -6286,9 +6319,11 @@
   }
 
   if (A.getKind() == ParsedAttr::AT_AlwaysDestroy)
-    handleSimpleAttributeWithExclusions<AlwaysDestroyAttr, NoDestroyAttr>(S, D, A);
+    handleSimpleAttributeWithExclusions<AlwaysDestroyAttr, NoDestroyAttr>(S, D,
+                                                                          A);
   else
-    handleSimpleAttributeWithExclusions<NoDestroyAttr, AlwaysDestroyAttr>(S, D, A);
+    handleSimpleAttributeWithExclusions<NoDestroyAttr, AlwaysDestroyAttr>(S, D,
+                                                                          A);
 }
 
 static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
@@ -6578,6 +6613,9 @@
   case ParsedAttr::AT_DiagnoseIf:
     handleDiagnoseIfAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_NoBuiltin:
+    handleNoBuiltinAttr(S, D, AL);
+    break;
   case ParsedAttr::AT_ExtVectorType:
     handleExtVectorTypeAttr(S, D, AL);
     break;
@@ -7277,8 +7315,8 @@
       S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
           << AL << AL.getRange();
     } else {
-      S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) << AL
-                                                            << AL.getRange();
+      S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl)
+          << AL << AL.getRange();
     }
   }
 }
@@ -7295,8 +7333,8 @@
 
 /// DeclClonePragmaWeak - clone existing decl (maybe definition),
 /// \#pragma weak needs a non-definition decl and source may not have one.
-NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
-                                      SourceLocation Loc) {
+NamedDecl *Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
+                                     SourceLocation Loc) {
   assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
   NamedDecl *NewD = nullptr;
   if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
@@ -7318,7 +7356,7 @@
     // a typedef.
     QualType FDTy = FD->getType();
     if (const auto *FT = FDTy->getAs<FunctionProtoType>()) {
-      SmallVector<ParmVarDecl*, 16> Params;
+      SmallVector<ParmVarDecl *, 16> Params;
       for (const auto &AI : FT->param_types()) {
         ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
         Param->setScopeInfo(0, Params.size());
@@ -7340,7 +7378,8 @@
 /// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak
 /// applied to it, possibly with an alias.
 void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
-  if (W.getUsed()) return; // only do this once
+  if (W.getUsed())
+    return; // only do this once
   W.setUsed(true);
   if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
     IdentifierInfo *NDId = ND->getIdentifier();
@@ -7421,8 +7460,7 @@
   // Private ivars are always okay.  Unfortunately, people don't
   // always properly make their ivars private, even in system headers.
   // Plus we need to make fields okay, too.
-  if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) &&
-      !isa<FunctionDecl>(D))
+  if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) && !isa<FunctionDecl>(D))
     return false;
 
   // Silently accept unsupported uses of __weak in both user and system
@@ -7550,8 +7588,8 @@
   // For +new, infer availability from -init.
   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
     if (S.NSAPIObj && ClassReceiver) {
-      ObjCMethodDecl *Init = ClassReceiver->lookupInstanceMethod(
-          S.NSAPIObj->getInitSelector());
+      ObjCMethodDecl *Init =
+          ClassReceiver->lookupInstanceMethod(S.NSAPIObj->getInitSelector());
       if (Init && Result == AR_Available && MD->isClassMethod() &&
           MD->getSelector() == S.NSAPIObj->getNewSelector() &&
           MD->definedInNSObject(S.getASTContext())) {
@@ -7564,7 +7602,6 @@
   return {Result, D};
 }
 
-
 /// whether we should emit a diagnostic for \c K and \c DeclVersion in
 /// the context of \c Ctx. For example, we should emit an unavailable diagnostic
 /// in a deprecated context, but not the other way around.
@@ -7759,14 +7796,11 @@
 /// may not be the same as ReferringDecl, i.e. if an EnumDecl is annotated and
 /// we refer to a member EnumConstantDecl, ReferringDecl is the EnumConstantDecl
 /// and OffendingDecl is the EnumDecl.
-static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
-                                      Decl *Ctx, const NamedDecl *ReferringDecl,
-                                      const NamedDecl *OffendingDecl,
-                                      StringRef Message,
-                                      ArrayRef<SourceLocation> Locs,
-                                      const ObjCInterfaceDecl *UnknownObjCClass,
-                                      const ObjCPropertyDecl *ObjCProperty,
-                                      bool ObjCPropertyAccess) {
+static void DoEmitAvailabilityWarning(
+    Sema &S, AvailabilityResult K, Decl *Ctx, const NamedDecl *ReferringDecl,
+    const NamedDecl *OffendingDecl, StringRef Message,
+    ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass,
+    const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess) {
   // Diagnostics for deprecated or unavailable.
   unsigned diag, diag_message, diag_fwdclass_message;
   unsigned diag_available_here = diag::note_availability_specified_here;
@@ -7898,7 +7932,8 @@
         };
 
         switch (AL->getImplicitReason()) {
-        case UnavailableAttr::IR_None: break;
+        case UnavailableAttr::IR_None:
+          break;
 
         case UnavailableAttr::IR_ARCForbiddenType:
           flagARCError();
@@ -7945,8 +7980,7 @@
 
     CharSourceRange UseRange;
     if (!Replacement.empty())
-      UseRange =
-          CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
+      UseRange = CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
     if (UseRange.isValid()) {
       if (const auto *MethodDecl = dyn_cast<ObjCMethodDecl>(ReferringDecl)) {
         Selector Sel = MethodDecl->getSelector();
@@ -7988,7 +8022,7 @@
   }
 
   S.Diag(NoteLocation, diag_available_here)
-    << OffendingDecl << available_here_select_kind;
+      << OffendingDecl << available_here_select_kind;
 }
 
 static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
@@ -8012,7 +8046,8 @@
   // When delaying diagnostics to run in the context of a parsed
   // declaration, we only want to actually emit anything if parsing
   // succeeds.
-  if (!decl) return;
+  if (!decl)
+    return;
 
   // We emit all the active diagnostics in this pool or any of its
   // parents.  In general, we'll get one pool for the decl spec
@@ -8024,10 +8059,11 @@
   const DelayedDiagnosticPool *pool = &poppedPool;
   do {
     bool AnyAccessFailures = false;
-    for (DelayedDiagnosticPool::pool_iterator
-           i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
+    for (DelayedDiagnosticPool::pool_iterator i = pool->pool_begin(),
+                                              e = pool->pool_end();
+         i != e; ++i) {
       // This const_cast is a bit lame.  Really, Triggered should be mutable.
-      DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i);
+      DelayedDiagnostic &diag = const_cast<DelayedDiagnostic &>(*i);
       if (diag.Triggered)
         continue;
 
@@ -8067,26 +8103,22 @@
   curPool->steal(pool);
 }
 
-static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR,
-                                    const NamedDecl *ReferringDecl,
-                                    const NamedDecl *OffendingDecl,
-                                    StringRef Message,
-                                    ArrayRef<SourceLocation> Locs,
-                                    const ObjCInterfaceDecl *UnknownObjCClass,
-                                    const ObjCPropertyDecl *ObjCProperty,
-                                    bool ObjCPropertyAccess) {
+static void EmitAvailabilityWarning(
+    Sema &S, AvailabilityResult AR, const NamedDecl *ReferringDecl,
+    const NamedDecl *OffendingDecl, StringRef Message,
+    ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass,
+    const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess) {
   // Delay if we're currently parsing a declaration.
   if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
-    S.DelayedDiagnostics.add(
-        DelayedDiagnostic::makeAvailability(
-            AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass,
-            ObjCProperty, Message, ObjCPropertyAccess));
+    S.DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
+        AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass, ObjCProperty,
+        Message, ObjCPropertyAccess));
     return;
   }
 
   Decl *Ctx = cast<Decl>(S.getCurLexicalContext());
-  DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl,
-                            Message, Locs, UnknownObjCClass, ObjCProperty,
+  DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl, Message,
+                            Locs, UnknownObjCClass, ObjCProperty,
                             ObjCPropertyAccess);
 }
 
@@ -8210,7 +8242,8 @@
 
   bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) {
     if (PRE->isClassReceiver())
-      DiagnoseDeclAvailability(PRE->getClassReceiver(), PRE->getReceiverLocation());
+      DiagnoseDeclAvailability(PRE->getClassReceiver(),
+                               PRE->getReceiverLocation());
     return true;
   }
 
@@ -8261,7 +8294,7 @@
       return;
 
     const AvailabilityAttr *AA =
-      getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl);
+        getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl);
     VersionTuple Introduced = AA->getIntroduced();
 
     if (AvailabilityStack.back() >= Introduced)
@@ -8345,8 +8378,9 @@
     const char *ExtraIndentation = "    ";
     std::string FixItString;
     llvm::raw_string_ostream FixItOS(FixItString);
-    FixItOS << "if (" << (SemaRef.getLangOpts().ObjC ? "@available"
-                                                     : "__builtin_available")
+    FixItOS << "if ("
+            << (SemaRef.getLangOpts().ObjC ? "@available"
+                                           : "__builtin_available")
             << "("
             << AvailabilityAttr::getPlatformNameSourceSpelling(
                    SemaRef.getASTContext().getTargetInfo().getPlatformName())
@@ -8443,7 +8477,7 @@
                                       ObjCInterfaceDecl *ClassReceiver) {
   std::string Message;
   AvailabilityResult Result;
-  const NamedDecl* OffendingDecl;
+  const NamedDecl *OffendingDecl;
   // See if this declaration is unavailable, deprecated, or partial.
   std::tie(Result, OffendingDecl) =
       ShouldDiagnoseAvailabilityOfDecl(*this, D, &Message, ClassReceiver);
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -9551,6 +9551,29 @@
     }
   }
 
+  // Diagnose no_builtin attribute on function declaration that are not a
+  // definition.
+  // FIXME: We should really be doing this in
+  // SemaDeclAttr.cpp::handleNoBuiltinAttr, unfortunately we only have access to
+  // the FunctionDecl and at this point of the code
+  // FunctionDecl::isThisDeclarationADefinition() which always returns `false`
+  // because Sema::ActOnStartOfFunctionDef has not been called yet.
+  if (const auto *NBA = NewFD->getAttr<NoBuiltinAttr>())
+    switch (D.getFunctionDefinitionKind()) {
+    case FDK_Defaulted:
+    case FDK_Deleted:
+      Diag(NBA->getLocation(),
+           diag::err_attribute_no_builtin_on_defaulted_deleted_function)
+          << NBA->getSpelling();
+      break;
+    case FDK_Declaration:
+      Diag(NBA->getLocation(), diag::err_attribute_no_builtin_on_non_definition)
+          << NBA->getSpelling();
+      break;
+    case FDK_Definition:
+      break;
+    }
+
   return NewFD;
 }
 
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1849,6 +1849,18 @@
       FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
     if (TargetDecl->hasAttr<ConvergentAttr>())
       FuncAttrs.addAttribute(llvm::Attribute::Convergent);
+    if (const auto *Attr = TargetDecl->getAttr<NoBuiltinAttr>()) {
+      bool HasWildcard = llvm::is_contained(Attr->builtinNames(), "*");
+      if (HasWildcard)
+        FuncAttrs.addAttribute("no-builtins");
+      else
+        for (StringRef BuiltinName : Attr->builtinNames()) {
+          SmallString<32> AttributeName;
+          AttributeName += "no-builtin-";
+          AttributeName += BuiltinName;
+          FuncAttrs.addAttribute(AttributeName);
+        }
+    }
 
     if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
       AddAttributesFromFunctionProtoType(
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3604,6 +3604,15 @@
 def err_attribute_overloadable_multiple_unmarked_overloads : Error<
   "at most one overload for a given name may lack the 'overloadable' "
   "attribute">;
+def warn_attribute_no_builtin_invalid_builtin_name : Warning<
+  "'%0' is not a valid builtin name for %1">,
+  InGroup<IgnoredAttributes>; // Which group should it be in?
+def err_attribute_no_builtin_wildcard_or_builtin_name : Error<
+  "empty %0 cannot be composed with named ones">;
+def err_attribute_no_builtin_on_non_definition : Error<
+  "%0 attribute is permitted on definitions only">;
+def err_attribute_no_builtin_on_defaulted_deleted_function : Error<
+  "%0 attribute has no effect on defaulted or deleted functions">;
 def warn_ns_attribute_wrong_return_type : Warning<
   "%0 attribute only applies to %select{functions|methods|properties}1 that "
   "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">,
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -4391,3 +4391,38 @@
 
 }];
 }
+
+def NoBuiltinDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+.. Note:: This attribute is not yet fully implemented, it is validated but has
+no effect on the generated code.
+
+The ``__attribute__((no_builtin))`` is similar to the ``-fno-builtin`` flag
+except it is specific to the body of a function. The attribute may also be
+applied to a virtual function but has no effect on the behavior of overriding
+functions in a derived class.
+
+It accepts one or more strings corresponding to the name of the builtin
+(e.g. "memcpy", "memset") or "*" which disables all builtins at once.
+
+.. code-block:: c++
+
+  // The compiler is not allowed to add any builtin to foo's body.
+  void foo(char* data, size_t count) __attribute__((no_builtin("*"))) {
+    // The compiler is not allowed to convert the loop into
+    // `__builtin_memset(data, 0xFE, count);`.
+    for (size_t i = 0; i < count; ++i)
+      data[i] = 0xFE;
+  }
+
+  // The compiler is not allowed to add the `memcpy` builtin to bar's body.
+  void bar(char* data, size_t count) __attribute__((no_builtin("memcpy"))) {
+    // The compiler is allowed to convert the loop into
+    // `__builtin_memset(data, 0xFE, count);` but cannot generate any
+    // `__builtin_memcpy`
+    for (size_t i = 0; i < count; ++i)
+      data[i] = 0xFE;
+  }
+  }];
+}
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -3420,3 +3420,10 @@
   let Subjects = SubjectList<[NonParmVar, Function, Block, ObjCMethod]>;
   let Documentation = [ObjCExternallyRetainedDocs];
 }
+
+def NoBuiltin : Attr {
+  let Spellings = [Clang<"no_builtin">];
+  let Args = [VariadicStringArgument<"BuiltinNames">];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [NoBuiltinDocs];
+}
Index: clang/include/clang/AST/Decl.h
===================================================================
--- clang/include/clang/AST/Decl.h
+++ clang/include/clang/AST/Decl.h
@@ -2030,6 +2030,10 @@
   ///
   /// This does not determine whether the function has been defined (e.g., in a
   /// previous definition); for that information, use isDefined.
+  ///
+  /// Note: the function declaration does not become a definition until the
+  /// parser reaches the definition, if called before, this function will return
+  /// `false`.
   bool isThisDeclarationADefinition() const {
     return isDeletedAsWritten() || isDefaulted() || Body || hasSkippedBody() ||
            isLateTemplateParsed() || willHaveBody() || hasDefiningAttr();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to