Skip to content

Commit

Permalink
Detect section type conflicts between functions and variables
Browse files Browse the repository at this point in the history
If two variables are declared with __attribute__((section(name))) and
the implicit section types (e.g. read only vs writeable) conflict, an
error is raised. Extend this mechanism so that an error is raised if the
section type implied by a function's __attribute__((section)) conflicts
with that of another variable.
  • Loading branch information
tmatheson-arm authored and AaronBallman committed Dec 17, 2020
1 parent 71699a9 commit f500662
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 15 deletions.
5 changes: 2 additions & 3 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -3086,13 +3086,12 @@ OPT_LIST(V)
};

struct SectionInfo {
DeclaratorDecl *Decl;
NamedDecl *Decl;
SourceLocation PragmaSectionLocation;
int SectionFlags;

SectionInfo() = default;
SectionInfo(DeclaratorDecl *Decl,
SourceLocation PragmaSectionLocation,
SectionInfo(NamedDecl *Decl, SourceLocation PragmaSectionLocation,
int SectionFlags)
: Decl(Decl), PragmaSectionLocation(PragmaSectionLocation),
SectionFlags(SectionFlags) {}
Expand Down
5 changes: 2 additions & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -9757,9 +9757,8 @@ class Sema final {
PSK_CodeSeg,
};

bool UnifySection(StringRef SectionName,
int SectionFlags,
DeclaratorDecl *TheDecl);
bool UnifySection(StringRef SectionName, int SectionFlags,
NamedDecl *TheDecl);
bool UnifySection(StringRef SectionName,
int SectionFlags,
SourceLocation PragmaSectionLocation);
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Sema/SemaAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,9 +481,8 @@ void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode);
}

bool Sema::UnifySection(StringRef SectionName,
int SectionFlags,
DeclaratorDecl *Decl) {
bool Sema::UnifySection(StringRef SectionName, int SectionFlags,
NamedDecl *Decl) {
SourceLocation PragmaLocation;
if (auto A = Decl->getAttr<SectionAttr>())
if (A->isImplicit())
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3081,8 +3081,14 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}

SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str);
if (NewAttr)
if (NewAttr) {
D->addAttr(NewAttr);
if (isa<FunctionDecl, FunctionTemplateDecl, ObjCMethodDecl,
ObjCPropertyDecl>(D))
S.UnifySection(NewAttr->getName(),
ASTContext::PSF_Execute | ASTContext::PSF_Read,
cast<NamedDecl>(D));
}
}

// This is used for `__declspec(code_seg("segname"))` on a decl.
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ void t72() { t71(); }
// CHECK: call void @t71() [[COLDSITE:#[0-9]+]]
// CHECK: declare void @t71() [[COLDDECL:#[0-9]+]]

// CHECK: define void @t10() [[NUW]] section "SECT" {
void t10(void) __attribute__((section("SECT")));
// CHECK: define void @t10() [[NUW]] section "xSECT" {
void t10(void) __attribute__((section("xSECT")));
void t10(void) {}
// CHECK: define void @t11() [[NUW]] section "SECT" {
void __attribute__((section("SECT"))) t11(void) {}
// CHECK: define void @t11() [[NUW]] section "xSECT" {
void __attribute__((section("xSECT"))) t11(void) {}

// CHECK: define i32 @t19() [[NUW]] {
extern int t19(void) __attribute__((weak_import));
Expand Down
20 changes: 19 additions & 1 deletion clang/test/Sema/attr-section.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,27 @@ extern int a __attribute__((section("foo,zed"))); // expected-warning {{section

// Not a warning.
int c;
int c __attribute__((section("foo,zed")));
int c __attribute__((section("seg1,sec1")));

// Also OK.
struct r_debug {};
extern struct r_debug _r_debug;
struct r_debug _r_debug __attribute__((nocommon, section(".r_debug,bar")));

// Section type conflicts between functions and variables
void test3(void) __attribute__((section("seg3,sec3"))); // expected-note {{declared here}}
void test3(void) {}
const int const_global_var __attribute__((section("seg3,sec3"))) = 10; // expected-error {{'const_global_var' causes a section type conflict with 'test3'}}

void test4(void) __attribute__((section("seg4,sec4"))); // expected-note {{declared here}}
void test4(void) {}
int mut_global_var __attribute__((section("seg4,sec4"))) = 10; // expected-error {{'mut_global_var' causes a section type conflict with 'test4'}}

const int global_seg5sec5 __attribute__((section("seg5,sec5"))) = 10; // expected-note {{declared here}}
void test5(void) __attribute__((section("seg5,sec5"))); // expected-error {{'test5' causes a section type conflict with 'global_seg5sec5'}}
void test5(void) {}

void test6(void);
const int global_seg6sec6 __attribute__((section("seg6,sec6"))) = 10; // expected-note {{declared here}}
void test6(void) __attribute__((section("seg6,sec6"))); // expected-error {{'test6' causes a section type conflict with 'global_seg6sec6'}}
void test6(void) {}
6 changes: 6 additions & 0 deletions clang/test/SemaCXX/attr-section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,9 @@ namespace override {
__attribute__((section("baz"))) // expected-warning {{section does not match}}
void C::f() {}
}

// Check for section type conflicts between global variables and function templates
template <typename> __attribute__((section("template_fn1"))) void template_fn1() {} // expected-note {{declared here}}
const int const_global_var __attribute__((section("template_fn1"))) = 42; // expected-error {{'const_global_var' causes a section type conflict with 'template_fn1'}}
int mut_global_var __attribute__((section("template_fn2"))) = 42; // expected-note {{declared here}}
template <typename> __attribute__((section("template_fn2"))) void template_fn2() {} // expected-error {{'template_fn2' causes a section type conflict with 'mut_global_var'}}
15 changes: 15 additions & 0 deletions clang/test/SemaObjC/method-attributes.m
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,18 @@ - (id) IMethod :(int) count, ... __attribute__((section("__TEXT,foo")));

+ (void) CMethod : (id) Obj __attribute__((section("__TEXT,fee")));
@end

// Section type conflicts between methods/properties and global variables
const int global1 __attribute__((section("seg1,sec1"))) = 10; // expected-note {{declared here}} expected-note {{declared here}} expected-note {{declared here}}
int global2 __attribute__((section("seg2,sec2"))) = 10; // expected-note {{declared here}} expected-note {{declared here}} expected-note {{declared here}}

@interface section_conflicts : NSObject
@property int p1 __attribute__((section("seg1,sec1"))); // expected-error {{'p1' causes a section type conflict with 'global1'}}
@property int p2 __attribute__((section("seg2,sec2"))); // expected-error {{'p2' causes a section type conflict with 'global2'}}

- (void)imethod1 __attribute__((section("seg1,sec1"))); // expected-error {{'imethod1' causes a section type conflict with 'global1'}}
- (void)imethod2 __attribute__((section("seg2,sec2"))); // expected-error {{'imethod2' causes a section type conflict with 'global2'}}

+ (void)cmethod1:(id)Obj __attribute__((section("seg1,sec1"))); // expected-error {{'cmethod1:' causes a section type conflict with 'global1'}}
+ (void)cmethod2:(id)Obj __attribute__((section("seg2,sec2"))); // expected-error {{'cmethod2:' causes a section type conflict with 'global2'}}
@end

0 comments on commit f500662

Please sign in to comment.