Meinersbur created this revision. Meinersbur added reviewers: hfinkel, aaron.ballman, nicholas, dlj, echristo, erichkeane.
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. Repository: rC Clang https://reviews.llvm.org/D50214 Files: include/clang/AST/DeclBase.h lib/AST/DeclBase.cpp test/Misc/ast-dump-attr.cpp test/Sema/attr-availability-ios.c test/Sema/attr-availability-tvos.c test/Sema/attr-availability-watchos.c
Index: test/Sema/attr-availability-watchos.c =================================================================== --- test/Sema/attr-availability-watchos.c +++ test/Sema/attr-availability-watchos.c @@ -32,8 +32,8 @@ 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}} Index: test/Sema/attr-availability-tvos.c =================================================================== --- test/Sema/attr-availability-tvos.c +++ test/Sema/attr-availability-tvos.c @@ -7,8 +7,8 @@ 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_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}} Index: test/Sema/attr-availability-ios.c =================================================================== --- test/Sema/attr-availability-ios.c +++ test/Sema/attr-availability-ios.c @@ -7,8 +7,8 @@ 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}} Index: test/Misc/ast-dump-attr.cpp =================================================================== --- test/Misc/ast-dump-attr.cpp +++ test/Misc/ast-dump-attr.cpp @@ -209,3 +209,24 @@ } } } + +// 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 Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -836,6 +836,29 @@ 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); Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -481,13 +481,7 @@ 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<attr_iterator>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits