diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 61e492b6f6d6355f92738f4f9fa03e7b24801417..969f23ea6cae0da4b0d07f967153d58a899f0f9f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -548,8 +548,10 @@ def err_implicit_pointer_address_space_cast : Error< "illegal implicit cast between two pointers with different address spaces">; def err_as_qualified_auto_decl : Error< "automatic variable qualified with an address space">; -def err_attribute_annotate_no_string : Error< - "argument to annotate attribute was not a string literal">; +def err_attribute_not_string : Error< + "argument to %0 attribute was not a string literal">; +def err_attribute_section_invalid_for_target : Error< + "argument to 'section' attribute is not valid for this target: %0">; def err_attribute_aligned_not_power_of_two : Error< "requested alignment is not a power of 2">; def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 8aa3378fec6611b8da889ace83de51f4657dde73..a34b8058c8f004fcc3138e96502a059a13d33b3c 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -21,14 +21,17 @@ #include <vector> #include <string> -namespace llvm { struct fltSemantics; } +namespace llvm { +struct fltSemantics; +class StringRef; +} namespace clang { class Diagnostic; +class SourceLocation; class SourceManager; class LangOptions; - namespace Builtin { struct Info; } /// TargetInfo - This class exposes information about the current target. @@ -324,6 +327,21 @@ public: virtual const char *getCFStringDataSection() const { return "__TEXT,__cstring,cstring_literals"; } + + + /// isValidSectionSpecifier - This is an optional hook that targets can + /// implement to perform semantic checking on attribute((section("foo"))) + /// specifiers. In this case, "foo" is passed in to be checked. If the + /// section specifier is invalid, the backend should return a non-empty string + /// that indicates the problem. + /// + /// This hook is a simple quality of implementation feature to catch errors + /// and give good diagnostics in cases when the assembler or code generator + /// would otherwise reject the section specifier. + /// + virtual std::string isValidSectionSpecifier(const llvm::StringRef &SR) const { + return ""; + } /// getDefaultLangOptions - Allow the target to specify default settings for /// various language options. These may be overridden by command line diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 51f5c87803e03d00be264654c5651a7135f6108c..605ee8c8d87f2d503a15839be1c2f1d842655906 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" +#include "llvm/MC/MCSectionMachO.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -61,6 +62,7 @@ static void DefineStd(std::vector<char> &Buf, const char *MacroName, //===----------------------------------------------------------------------===// // Defines specific to certain operating systems. //===----------------------------------------------------------------------===// + namespace { template<typename TgtInfo> class OSTargetInfo : public TgtInfo { @@ -78,7 +80,7 @@ public: }; } -namespace { + /// getDarwinNumber - Parse the 'darwin number' out of the specific targe /// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is /// not defined, return 0's. Return true if we have -darwin in the string or @@ -216,6 +218,7 @@ static void GetDarwinLanguageOptions(LangOptions &Opts, Opts.ObjCNonFragileABI = 1; } +namespace { template<typename Target> class DarwinTargetInfo : public OSTargetInfo<Target> { protected: @@ -245,8 +248,17 @@ public: virtual const char *getUnicodeStringSection() const { return "__TEXT,__ustring"; } + + virtual std::string isValidSectionSpecifier(const llvm::StringRef &SR) const { + // Let MCSectionMachO validate this. + llvm::StringRef Segment, Section; + unsigned TAA, StubSize; + return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section, + TAA, StubSize); + } }; + // DragonFlyBSD Target template<typename Target> class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> { diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 9d1b0849eff17ea2a87caca21e2db41655a01036..d5d3840569bf62c8737cb103152eb287f370bead 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -17,7 +17,7 @@ #include "clang/AST/Expr.h" #include "clang/Basic/TargetInfo.h" #include "clang/Parse/DeclSpec.h" -#include <llvm/ADT/StringExtras.h> +#include "llvm/ADT/StringExtras.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -981,15 +981,25 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { // Make sure that there is a string literal as the sections's single // argument. - StringLiteral *SE = - dyn_cast<StringLiteral>(static_cast<Expr *>(Attr.getArg(0))); + Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0)); + StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); if (!SE) { - // FIXME - S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); + S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section"; return; } - D->addAttr(::new (S.Context) SectionAttr(std::string(SE->getStrData(), - SE->getByteLength()))); + + std::string SectionStr(SE->getStrData(), SE->getByteLength()); + + // If the target wants to validate the section specifier, make it happen. + std::string Error = S.Context.Target.isValidSectionSpecifier(SectionStr); + if (Error.empty()) { + D->addAttr(::new (S.Context) SectionAttr(SectionStr)); + return; + } + + S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target) + << Error; + } static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1405,13 +1415,13 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } - Expr *argExpr = static_cast<Expr *>(Attr.getArg(0)); - StringLiteral *SE = dyn_cast<StringLiteral>(argExpr); + Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0)); + StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); // Make sure that there is a string literal as the annotation's single // argument. if (!SE) { - S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); + S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; return; } d->addAttr(::new (S.Context) AnnotateAttr(std::string(SE->getStrData(), diff --git a/test/Sema/attr-section.c b/test/Sema/attr-section.c new file mode 100644 index 0000000000000000000000000000000000000000..c61ed80cbf7a9dc065c4aa7494c5fbcc34c6de1c --- /dev/null +++ b/test/Sema/attr-section.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -verify -fsyntax-only -triple x86_64-apple-darwin9 %s + +int x __attribute__((section( + 42))); // expected-error {{argument to section attribute was not a string literal}} + + +// rdar://4341926 +int y __attribute__((section( + "sadf"))); // expected-error {{mach-o section specifier requires a segment and section separated by a comma}} + diff --git a/tools/index-test/CMakeLists.txt b/tools/index-test/CMakeLists.txt index 880539bbe31b16b419ef774ceb273df33b08e497..9c9656a1130e67742c1ce2eab3182f6bbf2682a6 100644 --- a/tools/index-test/CMakeLists.txt +++ b/tools/index-test/CMakeLists.txt @@ -11,6 +11,7 @@ set( LLVM_USED_LIBS set( LLVM_LINK_COMPONENTS bitreader + mc ) add_clang_executable(index-test diff --git a/tools/index-test/Makefile b/tools/index-test/Makefile index cec0eee2861757ad7076755591068fe8312c32c1..0a43d2f47f9c6b4a6107e78e1ae2ea982dbc634b 100644 --- a/tools/index-test/Makefile +++ b/tools/index-test/Makefile @@ -17,7 +17,7 @@ TOOL_NO_EXPORTS = 1 include $(LEVEL)/Makefile.config -LINK_COMPONENTS := bitreader +LINK_COMPONENTS := bitreader mc USEDLIBS = clangIndex.a clangFrontend.a clangSema.a clangAST.a clangLex.a clangBasic.a include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/wpa/CMakeLists.txt b/tools/wpa/CMakeLists.txt index 5ba3bc8a18b5c8e5df75a149d95914099e2cae0d..5553474b4bcd502f93f2ae88d843e8c7ea42f2bb 100644 --- a/tools/wpa/CMakeLists.txt +++ b/tools/wpa/CMakeLists.txt @@ -11,6 +11,7 @@ set( LLVM_USED_LIBS ) set( LLVM_LINK_COMPONENTS + mc ) add_clang_executable(clang-wpa diff --git a/tools/wpa/Makefile b/tools/wpa/Makefile index c15be3f828d2f2c4c8cf8268d9b0635710804bf3..ddde5b288bc83ca57bae92576a4f8b082f4d9285 100644 --- a/tools/wpa/Makefile +++ b/tools/wpa/Makefile @@ -9,7 +9,7 @@ TOOL_NO_EXPORTS = 1 include $(LEVEL)/Makefile.config -LINK_COMPONENTS := bitreader +LINK_COMPONENTS := bitreader mc USEDLIBS = clangFrontend.a clangSema.a clangAST.a clangLex.a clangBasic.a clangAnalysis.a clangIndex.a include $(LLVM_SRC_ROOT)/Makefile.rules