From: Michael Kruse Date: Mon, 24 Sep 2018 06:31:37 +0000 (+0000) Subject: Add inherited attributes before parsed attributes. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9884fc1d0881576784e9b50da9eb61a5eb427f1c;p=clang Add inherited attributes before parsed attributes. Currently, attributes from previous declarations ('inherited attributes') are added to the end of a declaration's list of attributes. Before r338800, the attribute list was in reverse. r338800 changed the order of non-inherited (parsed from the current declaration) attributes, but inherited attributes are still appended to the end of the list. This patch appends inherited attributes after other inherited attributes, but before any non-inherited attribute. This is to make the order of attributes in the AST correspond to the order in the source code. Differential Revision: https://reviews.llvm.org/D50214 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342861 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index c174242a90..23870400a3 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -482,13 +482,7 @@ public: const AttrVec &getAttrs() const; void dropAttrs(); - - void addAttr(Attr *A) { - if (hasAttrs()) - getAttrs().push_back(A); - else - setAttrs(AttrVec(1, A)); - } + void addAttr(Attr *A); using attr_iterator = AttrVec::const_iterator; using attr_range = llvm::iterator_range; diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 6bb2034a9e..b706e504a3 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -836,6 +836,29 @@ void Decl::dropAttrs() { getASTContext().eraseDeclAttrs(this); } +void Decl::addAttr(Attr *A) { + if (!hasAttrs()) { + setAttrs(AttrVec(1, A)); + return; + } + + AttrVec &Attrs = getAttrs(); + if (!A->isInherited()) { + Attrs.push_back(A); + return; + } + + // Attribute inheritance is processed after attribute parsing. To keep the + // order as in the source code, add inherited attributes before non-inherited + // ones. + auto I = Attrs.begin(), E = Attrs.end(); + for (; I != E; ++I) { + if (!(*I)->isInherited()) + break; + } + Attrs.insert(I, A); +} + const AttrVec &Decl::getAttrs() const { assert(HasAttrs && "No attrs to get!"); return getASTContext().getDeclAttrs(this); diff --git a/test/Misc/ast-dump-attr.cpp b/test/Misc/ast-dump-attr.cpp index 1e4eb7c319..5ed3c73aa2 100644 --- a/test/Misc/ast-dump-attr.cpp +++ b/test/Misc/ast-dump-attr.cpp @@ -209,3 +209,24 @@ namespace TestSuppress { } } } + +// Verify the order of attributes in the Ast. It must reflect the order +// in the parsed source. +int mergeAttrTest() __attribute__((deprecated)) __attribute__((warn_unused_result)); +int mergeAttrTest() __attribute__((annotate("test"))); +int mergeAttrTest() __attribute__((unused,no_thread_safety_analysis)); +// CHECK: FunctionDecl{{.*}} mergeAttrTest +// CHECK-NEXT: DeprecatedAttr +// CHECK-NEXT: WarnUnusedResultAttr + +// CHECK: FunctionDecl{{.*}} mergeAttrTest +// CHECK-NEXT: DeprecatedAttr{{.*}} Inherited +// CHECK-NEXT: WarnUnusedResultAttr{{.*}} Inherited +// CHECK-NEXT: AnnotateAttr{{.*}} + +// CHECK: FunctionDecl{{.*}} mergeAttrTest +// CHECK-NEXT: DeprecatedAttr{{.*}} Inherited +// CHECK-NEXT: WarnUnusedResultAttr{{.*}} Inherited +// CHECK-NEXT: AnnotateAttr{{.*}} Inherited +// CHECK-NEXT: UnusedAttr +// CHECK-NEXT: NoThreadSafetyAnalysisAttr diff --git a/test/Sema/attr-availability-ios.c b/test/Sema/attr-availability-ios.c index 3f901bb33c..f418c7dcfd 100644 --- a/test/Sema/attr-availability-ios.c +++ b/test/Sema/attr-availability-ios.c @@ -7,8 +7,8 @@ void f3(int) __attribute__((availability(ios,introduced=3.0))); void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(ios,introduced=2.0,deprecated=2.1,obsoleted=3.0))); // expected-note{{explicitly marked unavailable}} void f5(int) __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f5' has been explicitly marked deprecated here}} -void f6(int) __attribute__((availability(ios,deprecated=3.0))); -void f6(int) __attribute__((availability(iOS,introduced=2.0))); // expected-note {{'f6' has been explicitly marked deprecated here}} +void f6(int) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f6' has been explicitly marked deprecated here}} +void f6(int) __attribute__((availability(iOS,introduced=2.0))); void test() { f0(0); // expected-warning{{'f0' is deprecated: first deprecated in iOS 2.1}} diff --git a/test/Sema/attr-availability-tvos.c b/test/Sema/attr-availability-tvos.c index 4f8c4588ec..b940a9ad3a 100644 --- a/test/Sema/attr-availability-tvos.c +++ b/test/Sema/attr-availability-tvos.c @@ -7,8 +7,8 @@ void f3(int) __attribute__((availability(tvos,introduced=3.0))); void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(tvos,introduced=2.0,deprecated=2.1,obsoleted=3.0))); // expected-note{{explicitly marked unavailable}} void f5(int) __attribute__((availability(tvos,introduced=2.0))) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f5' has been explicitly marked deprecated here}} -void f6(int) __attribute__((availability(tvos,deprecated=3.0))); -void f6(int) __attribute__((availability(tvos,introduced=2.0))); // expected-note {{'f6' has been explicitly marked deprecated here}} +void f6(int) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f6' has been explicitly marked deprecated here}} +void f6(int) __attribute__((availability(tvos,introduced=2.0))); void test() { f0(0); // expected-warning{{'f0' is deprecated: first deprecated in tvOS 2.1}} @@ -41,8 +41,8 @@ void f5_tvos(int) __attribute__((availability(tvos,introduced=2.0))) __attribute void f5_attr_reversed_tvos(int) __attribute__((availability(ios, deprecated=3.0))) __attribute__((availability(tvos,introduced=2.0))); void f5b_tvos(int) __attribute__((availability(tvos,introduced=2.0))) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f5b_tvos' has been explicitly marked deprecated here}} void f5c_tvos(int) __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f5c_tvos' has been explicitly marked deprecated here}} -void f6_tvos(int) __attribute__((availability(tvos,deprecated=3.0))); -void f6_tvos(int) __attribute__((availability(tvOS,introduced=2.0))); // expected-note {{'f6_tvos' has been explicitly marked deprecated here}} +void f6_tvos(int) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f6_tvos' has been explicitly marked deprecated here}} +void f6_tvos(int) __attribute__((availability(tvOS,introduced=2.0))); void test_tvos() { f0_tvos(0); // expected-warning{{'f0_tvos' is deprecated: first deprecated in tvOS 2.1}} diff --git a/test/Sema/attr-availability-watchos.c b/test/Sema/attr-availability-watchos.c index 59233986ee..866efac6a0 100644 --- a/test/Sema/attr-availability-watchos.c +++ b/test/Sema/attr-availability-watchos.c @@ -32,8 +32,8 @@ void f5_watchos(int) __attribute__((availability(watchos,introduced=2.0))) __att void f5_attr_reversed_watchos(int) __attribute__((availability(ios, deprecated=3.0))) __attribute__((availability(watchos,introduced=2.0))); void f5b_watchos(int) __attribute__((availability(watchos,introduced=2.0))) __attribute__((availability(watchos,deprecated=3.0))); // expected-note {{'f5b_watchos' has been explicitly marked deprecated here}} void f5c_watchos(int) __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f5c_watchos' has been explicitly marked deprecated here}} -void f6_watchos(int) __attribute__((availability(watchos,deprecated=3.0))); -void f6_watchos(int) __attribute__((availability(watchOS,introduced=2.0))); // expected-note {{'f6_watchos' has been explicitly marked deprecated here}} +void f6_watchos(int) __attribute__((availability(watchos,deprecated=3.0))); // expected-note {{'f6_watchos' has been explicitly marked deprecated here}} +void f6_watchos(int) __attribute__((availability(watchOS,introduced=2.0))); void test_watchos() { f0_watchos(0); // expected-warning{{'f0_watchos' is deprecated: first deprecated in watchOS 2.1}}