From ce850d4bf51a1683be1a5e18243162c80f0eaf32 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer <benny.kra@googlemail.com> Date: Thu, 28 Apr 2016 12:14:47 +0000 Subject: [PATCH] Revert r267784, r267824 and r267830. It makes compiler-rt tests fail if the gold plugin is enabled. Revert "Rework interface for bitset-using features to use a notion of LTO visibility." Revert "Driver: only produce CFI -fvisibility= error when compiling." Revert "clang/test/CodeGenCXX/cfi-blacklist.cpp: Exclude ms targets. They would be non-cfi." git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@267871 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ControlFlowIntegrity.rst | 36 +++---- docs/LTOVisibility.rst | 111 -------------------- docs/UsersManual.rst | 13 ++- docs/index.rst | 1 - include/clang/Basic/Attr.td | 6 -- include/clang/Basic/AttrDocs.td | 7 -- include/clang/Driver/CC1Options.td | 3 - include/clang/Driver/Options.td | 3 + include/clang/Frontend/CodeGenOptions.def | 4 - include/clang/Frontend/CodeGenOptions.h | 3 + lib/CodeGen/CGClass.cpp | 9 +- lib/CodeGen/CGVTables.cpp | 57 +++++----- lib/CodeGen/CodeGenModule.cpp | 4 +- lib/CodeGen/CodeGenModule.h | 12 ++- lib/CodeGen/MicrosoftCXXABI.cpp | 17 +-- lib/Driver/SanitizerArgs.cpp | 11 -- lib/Driver/Tools.cpp | 39 ++++--- lib/Frontend/CompilerInvocation.cpp | 3 +- lib/Sema/SemaDeclAttr.cpp | 3 - runtime/CMakeLists.txt | 13 +++ runtime/vtables_blacklist.txt | 8 ++ test/CodeGenCXX/bitset-blacklist.cpp | 32 ++++++ test/CodeGenCXX/bitset-inference.cpp | 107 ------------------- test/CodeGenCXX/bitsets.cpp | 16 +-- test/CodeGenCXX/cfi-blacklist.cpp | 29 ----- test/CodeGenCXX/cfi-cast.cpp | 34 +++--- test/CodeGenCXX/cfi-cross-dso.cpp | 4 +- test/CodeGenCXX/cfi-ms-rtti.cpp | 4 +- test/CodeGenCXX/cfi-nvcall.cpp | 4 +- test/CodeGenCXX/cfi-stats.cpp | 2 +- test/Driver/cl-runtime-flags.c | 2 - test/Driver/fsanitize.c | 22 ++-- test/Driver/whole-program-vtables.c | 9 ++ test/Frontend/dependency-gen.c | 2 +- test/SemaCXX/attr-lto-visibility-public.cpp | 14 --- 35 files changed, 209 insertions(+), 435 deletions(-) delete mode 100644 docs/LTOVisibility.rst create mode 100644 runtime/vtables_blacklist.txt create mode 100644 test/CodeGenCXX/bitset-blacklist.cpp delete mode 100644 test/CodeGenCXX/bitset-inference.cpp delete mode 100644 test/CodeGenCXX/cfi-blacklist.cpp delete mode 100644 test/SemaCXX/attr-lto-visibility-public.cpp diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst index eed5ac51200..c403610952c 100644 --- a/docs/ControlFlowIntegrity.rst +++ b/docs/ControlFlowIntegrity.rst @@ -25,25 +25,13 @@ As currently implemented, all schemes rely on link-time optimization (LTO); so it is required to specify ``-flto``, and the linker used must support LTO, for example via the `gold plugin`_. -To allow the checks to be implemented efficiently, the program must -be structured such that certain object files are compiled with CFI +To allow the checks to be implemented efficiently, the program must be +structured such that certain object files are compiled with CFI enabled, and are statically linked into the program. This may preclude -the use of shared libraries in some cases. - -The compiler will only produce CFI checks for a class if it can infer hidden -LTO visibility for that class. LTO visibility is a property of a class that -is inferred from flags and attributes. For more details, see the documentation -for :doc:`LTO visibility <LTOVisibility>`. - -The ``-fsanitize=cfi-{vcall,nvcall,derived-cast,unrelated-cast}`` flags -require that a ``-fvisibility=`` flag also be specified. This is because the -default visibility setting is ``-fvisibility=default``, which would disable -CFI checks for classes without visibility attributes. Most users will want -to specify ``-fvisibility=hidden``, which enables CFI checks for such classes. - -Experimental support for :ref:`cross-DSO control flow integrity -<cfi-cross-dso>` exists that does not require classes to have hidden LTO -visibility. This cross-DSO support has unstable ABI at this time. +the use of shared libraries in some cases. Experimental support for +:ref:`cross-DSO control flow integrity <cfi-cross-dso>` exists that +does not have these requirements. This cross-DSO support has unstable +ABI at this time. .. _gold plugin: http://llvm.org/docs/GoldPlugin.html @@ -245,6 +233,11 @@ A :doc:`SanitizerSpecialCaseList` can be used to relax CFI checks for certain source files, functions and types using the ``src``, ``fun`` and ``type`` entity types. +In addition, if a type has a ``uuid`` attribute and the blacklist contains +the type entry ``attr:uuid``, CFI checks are suppressed for that type. This +allows all COM types to be easily blacklisted, which is useful as COM types +are typically defined outside of the linked program. + .. code-block:: bash # Suppress checking for code in a file. @@ -254,6 +247,8 @@ entity types. fun:*MyFooBar* # Ignore all types in the standard library. type:std::* + # Ignore all types with a uuid attribute. + type:attr:uuid .. _cfi-cross-dso: @@ -265,11 +260,6 @@ flow integrity mode, which allows all CFI schemes listed above to apply across DSO boundaries. As in the regular CFI, each DSO must be built with ``-flto``. -Normally, CFI checks will only be performed for classes that have hidden LTO -visibility. With this flag enabled, the compiler will emit cross-DSO CFI -checks for all classes, except for those which appear in the CFI blacklist -or which use a ``no_sanitize`` attribute. - Design ====== diff --git a/docs/LTOVisibility.rst b/docs/LTOVisibility.rst deleted file mode 100644 index 21a3157c834..00000000000 --- a/docs/LTOVisibility.rst +++ /dev/null @@ -1,111 +0,0 @@ -============== -LTO Visibility -============== - -*LTO visibility* is a property of an entity that specifies whether it can be -referenced from outside the current LTO unit. A *linkage unit* is a set of -translation units linked together into an executable or DSO, and a linkage -unit's *LTO unit* is the subset of the linkage unit that is linked together -using link-time optimization; in the case where LTO is not being used, the -linkage unit's LTO unit is empty. Each linkage unit has only a single LTO unit. - -The LTO visibility of a class is used by the compiler to determine which -classes the virtual function call optimization and control flow integrity -features apply to. These features use whole-program information, so they -require the entire class hierarchy to be visible in order to work correctly. - -If any translation unit in the program uses either of the virtual function -call optimization or control flow integrity features, it is effectively an -ODR violation to define a class with hidden LTO visibility in multiple linkage -units. A class with public LTO visibility may be defined in multiple linkage -units, but the tradeoff is that the virtual function call optimization and -control flow integrity features can only be applied to classes with hidden LTO -visibility. A class's LTO visibility is treated as an ODR-relevant property -of its definition, so it must be consistent between translation units. - -In translation units built with LTO, LTO visibility is based on symbol -visibility or, on the Windows platform, the dllimport and dllexport -attributes. When targeting non-Windows platforms, classes with a visibility -other than hidden visibility receive public LTO visibility. When targeting -Windows, classes with dllimport or dllexport attributes receive public LTO -visibility. All other classes receive hidden LTO visibility. Classes with -internal linkage (e.g. classes declared in unnamed namespaces) also receive -hidden LTO visibility. - -A class defined in a translation unit built without LTO receives public -LTO visibility regardless of its object file visibility, linkage or other -attributes. - -This mechanism will produce the correct result in most cases, but there are -two cases where it may wrongly infer hidden LTO visibility. - -1. As a corollary of the above rules, if a linkage unit is produced from a - combination of LTO object files and non-LTO object files, any hidden - visibility class defined in both a translation unit built with LTO and - a translation unit built without LTO must be defined with public LTO - visibility in order to avoid an ODR violation. - -2. Some ABIs provide the ability to define an abstract base class without - visibility attributes in multiple linkage units and have virtual calls - to derived classes in other linkage units work correctly. One example of - this is COM on Windows platforms. If the ABI allows this, any base class - used in this way must be defined with public LTO visibility. - -Classes that fall into either of these categories can be marked up with the -``[[clang::lto_visibility_public]]`` attribute. To specifically handle the -COM case, classes with the ``__declspec(uuid())`` attribute receive public -LTO visibility. On Windows platforms, clang-cl's ``/MT`` and ``/MTd`` -flags statically link the program against a prebuilt standard library; -these flags imply public LTO visibility for every class declared in the -``std`` and ``stdext`` namespaces. - -Example -======= - -The following example shows how LTO visibility works in practice in several -cases involving two linkage units, ``main`` and ``dso.so``. - -.. code-block:: none - - +-----------------------------------------------------------+ +----------------------------------------------------+ - | main (clang++ -fvisibility=hidden): | | dso.so (clang++ -fvisibility=hidden): | - | | | | - | +-----------------------------------------------------+ | | struct __attribute__((visibility("default"))) C { | - | | LTO unit (clang++ -fvisibility=hidden -flto): | | | virtual void f(); | - | | | | | } | - | | struct A { ... }; | | | void C::f() {} | - | | struct [[clang::lto_visibility_public]] B { ... }; | | | struct D { | - | | struct __attribute__((visibility("default"))) C { | | | virtual void g() = 0; | - | | virtual void f(); | | | }; | - | | }; | | | struct E : D { | - | | struct [[clang::lto_visibility_public]] D { | | | virtual void g() { ... } | - | | virtual void g() = 0; | | | }; | - | | }; | | | __attribute__(visibility("default"))) D *mkE() { | - | | | | | return new E; | - | +-----------------------------------------------------+ | | } | - | | | | - | struct B { ... }; | +----------------------------------------------------+ - | | - +-----------------------------------------------------------+ - -We will now describe the LTO visibility of each of the classes defined in -these linkage units. - -Class ``A`` is not defined outside of ``main``'s LTO unit, so it can have -hidden LTO visibility. This is inferred from the object file visibility -specified on the command line. - -Class ``B`` is defined in ``main``, both inside and outside its LTO unit. The -definition outside the LTO unit has public LTO visibility, so the definition -inside the LTO unit must also have public LTO visibility in order to avoid -an ODR violation. - -Class ``C`` is defined in both ``main`` and ``dso.so`` and therefore must -have public LTO visibility. This is correctly inferred from the ``visibility`` -attribute. - -Class ``D`` is an abstract base class with a derived class ``E`` defined -in ``dso.so``. This is an example of the COM scenario; the definition of -``D`` in ``main``'s LTO unit must have public LTO visibility in order to be -compatible with the definition of ``D`` in ``dso.so``, which is observable -by calling the function ``mkE``. diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst index 7a9bdb96c5b..34e4408719c 100644 --- a/docs/UsersManual.rst +++ b/docs/UsersManual.rst @@ -1056,8 +1056,17 @@ are listed below. .. option:: -fwhole-program-vtables Enable whole-program vtable optimizations, such as single-implementation - devirtualization and virtual constant propagation, for classes with - :doc:`hidden LTO visibility <LTOVisibility>`. Requires ``-flto``. + devirtualization and virtual constant propagation. Requires ``-flto``. + + By default, the compiler will assume that all type hierarchies are + closed except those in the ``std`` namespace, the ``stdext`` namespace + and classes with the ``__declspec(uuid())`` attribute. + +.. option:: -fwhole-program-vtables-blacklist=path + + Allows the user to specify the path to a list of additional classes to + blacklist from whole-program vtable optimizations. This list is in the + :ref:`CFI blacklist <cfi-blacklist>` format. .. option:: -fno-assume-sane-operator-new diff --git a/docs/index.rst b/docs/index.rst index f287911d3c3..6028fb8ec2f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,7 +31,6 @@ Using Clang as a Compiler SanitizerStats SanitizerSpecialCaseList ControlFlowIntegrity - LTOVisibility SafeStack Modules MSVCCompatibility diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index d5dcdc06354..1f86b09cc97 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -1611,12 +1611,6 @@ def WeakRef : InheritableAttr { let Documentation = [Undocumented]; } -def LTOVisibilityPublic : InheritableAttr { - let Spellings = [CXX11<"clang", "lto_visibility_public">]; - let Subjects = SubjectList<[Record]>; - let Documentation = [LTOVisibilityDocs]; -} - def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> { // NOTE: If you add any additional spellings, ARMInterrupt's, // MSP430Interrupt's and MipsInterrupt's spellings must match. diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 39c4257ddfe..b1b9e444383 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -2380,10 +2380,3 @@ The ``ifunc`` attribute may only be used on a function declaration. A function Not all targets support this attribute. ELF targets support this attribute when using binutils v2.20.1 or higher and glibc v2.11.1 or higher. Non-ELF targets currently do not support this attribute. }]; } - -def LTOVisibilityDocs : Documentation { - let Category = DocCatType; - let Content = [{ -See :doc:`LTOVisibility`. - }]; -} diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 7c1777fc186..e88e4bd259f 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -282,9 +282,6 @@ def fprofile_instrument_path_EQ : Joined<["-"], "fprofile-instrument-path=">, def fprofile_instrument_use_path_EQ : Joined<["-"], "fprofile-instrument-use-path=">, HelpText<"Specify the profile path in PGO use compilation">; -def flto_visibility_public_std: - Flag<["-"], "flto-visibility-public-std">, - HelpText<"Use public LTO visibility for classes in std and stdext namespaces">; //===----------------------------------------------------------------------===// // Dependency Output Options diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index aaa4ce92f7b..d2e66572884 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1152,6 +1152,9 @@ def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Grou Flags<[CC1Option]>, HelpText<"Enables whole-program vtable optimization. Requires -flto">; def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>; +def fwhole_program_vtables_blacklist_EQ : Joined<["-"], "fwhole-program-vtables-blacklist=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Path to a blacklist file for whole-program vtable optimization">; def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Treat signed integer overflow as two's complement">; def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 49b306fd777..14a6ae50c1a 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -187,10 +187,6 @@ CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists. CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program /// vtable optimization. -/// Whether to use public LTO visibility for entities in std and stdext -/// namespaces. This is enabled by clang-cl's /MT and /MTd flags. -CODEGENOPT(LTOVisibilityPublicStd, 1, 0) - /// The user specified number of registers to be used for integral arguments, /// or 0 if unspecified. VALUE_CODEGENOPT(NumRegisterParameters, 32, 0) diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 71acfc6da40..be176df7f7b 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -199,6 +199,9 @@ public: /// \brief A list of all -fno-builtin-* function names (e.g., memset). std::vector<std::string> NoBuiltinFuncs; + /// List of blacklist files for the whole-program vtable optimization feature. + std::vector<std::string> WholeProgramVTablesBlacklistFiles; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 71b305c773d..351dae9d4dd 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -2489,7 +2489,7 @@ void CodeGenFunction::EmitBitSetCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable, SourceLocation Loc) { if (CGM.getCodeGenOpts().WholeProgramVTables && - CGM.HasHiddenLTOVisibility(RD)) { + !CGM.IsBitSetBlacklistedRecord(RD)) { llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); llvm::Value *BitSetName = @@ -2565,12 +2565,7 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable, CFITypeCheckKind TCK, SourceLocation Loc) { - if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso && - !CGM.HasHiddenLTOVisibility(RD)) - return; - - std::string TypeName = RD->getQualifiedNameAsString(); - if (getContext().getSanitizerBlacklist().isBlacklistedType(TypeName)) + if (CGM.IsBitSetBlacklistedRecord(RD)) return; SanitizerScope SanScope(this); diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 478164e273b..f139e2c8504 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -902,43 +902,34 @@ void CodeGenModule::EmitDeferredVTables() { DeferredVTables.clear(); } -bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) { - LinkageInfo LV = RD->getLinkageAndVisibility(); - if (!isExternallyVisible(LV.getLinkage())) - return true; - - if (RD->hasAttr<LTOVisibilityPublicAttr>() || RD->hasAttr<UuidAttr>()) - return false; +bool CodeGenModule::NeedVTableBitSets() { + return getCodeGenOpts().WholeProgramVTables || + getLangOpts().Sanitize.has(SanitizerKind::CFIVCall) || + getLangOpts().Sanitize.has(SanitizerKind::CFINVCall) || + getLangOpts().Sanitize.has(SanitizerKind::CFIDerivedCast) || + getLangOpts().Sanitize.has(SanitizerKind::CFIUnrelatedCast); +} - if (getTriple().isOSBinFormatCOFF()) { - if (RD->hasAttr<DLLExportAttr>() || RD->hasAttr<DLLImportAttr>()) - return false; - } else { - if (LV.getVisibility() != HiddenVisibility) - return false; - } +bool CodeGenModule::IsBitSetBlacklistedRecord(const CXXRecordDecl *RD) { + std::string TypeName = RD->getQualifiedNameAsString(); + auto isInBlacklist = [&](const SanitizerBlacklist &BL) { + if (RD->hasAttr<UuidAttr>() && BL.isBlacklistedType("attr:uuid")) + return true; - if (getCodeGenOpts().LTOVisibilityPublicStd) { - const DeclContext *DC = RD; - while (1) { - auto *D = cast<Decl>(DC); - DC = DC->getParent(); - if (isa<TranslationUnitDecl>(DC->getRedeclContext())) { - if (auto *ND = dyn_cast<NamespaceDecl>(D)) - if (const IdentifierInfo *II = ND->getIdentifier()) - if (II->isStr("std") || II->isStr("stdext")) - return false; - break; - } - } - } + return BL.isBlacklistedType(TypeName); + }; - return true; + return isInBlacklist(WholeProgramVTablesBlacklist) || + ((LangOpts.Sanitize.has(SanitizerKind::CFIVCall) || + LangOpts.Sanitize.has(SanitizerKind::CFINVCall) || + LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) || + LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast)) && + isInBlacklist(getContext().getSanitizerBlacklist())); } void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable, const VTableLayout &VTLayout) { - if (!getCodeGenOpts().PrepareForLTO) + if (!NeedVTableBitSets()) return; CharUnits PointerWidth = @@ -947,8 +938,12 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable, typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry; std::vector<BSEntry> BitsetEntries; // Create a bit set entry for each address point. - for (auto &&AP : VTLayout.getAddressPoints()) + for (auto &&AP : VTLayout.getAddressPoints()) { + if (IsBitSetBlacklistedRecord(AP.first.getBase())) + continue; + BitsetEntries.push_back(std::make_pair(AP.first.getBase(), AP.second)); + } // Sort the bit set entries for determinism. std::sort(BitsetEntries.begin(), BitsetEntries.end(), diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 8ff99a6c404..64fe3652a9d 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -88,7 +88,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), Target(C.getTargetInfo()), ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this), VTables(*this), - SanitizerMD(new SanitizerMetadata(*this)) { + SanitizerMD(new SanitizerMetadata(*this)), + WholeProgramVTablesBlacklist(CGO.WholeProgramVTablesBlacklistFiles, + C.getSourceManager()) { // Initialize the type cache. llvm::LLVMContext &LLVMContext = M.getContext(); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index a75e4aa2a32..34d1111889a 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -490,6 +490,8 @@ private: /// MDNodes. llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap; + SanitizerBlacklist WholeProgramVTablesBlacklist; + public: CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts, const PreprocessorOptions &ppopts, @@ -1113,10 +1115,12 @@ public: void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D, CodeGenFunction *CGF = nullptr); - /// Returns whether the given record has hidden LTO visibility and therefore - /// may participate in (single-module) CFI and whole-program vtable - /// optimization. - bool HasHiddenLTOVisibility(const CXXRecordDecl *RD); + /// Returns whether we need bit sets attached to vtables. + bool NeedVTableBitSets(); + + /// Returns whether the given record is blacklisted from whole-program + /// transformations (i.e. CFI or whole-program vtable optimization). + bool IsBitSetBlacklistedRecord(const CXXRecordDecl *RD); /// Emit bit set entries for the given vtable using the given layout if /// vptr CFI is enabled. diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 0e15f5054d8..e578863bfc3 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1503,7 +1503,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, const CXXRecordDecl *RD, llvm::GlobalVariable *VTable) { - if (!CGM.getCodeGenOpts().PrepareForLTO) + if (!CGM.NeedVTableBitSets()) return; llvm::NamedMDNode *BitsetsMD = @@ -1519,13 +1519,15 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, : CharUnits::Zero(); if (Info->PathToBaseWithVPtr.empty()) { - CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD); + if (!CGM.IsBitSetBlacklistedRecord(RD)) + CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD); return; } // Add a bitset entry for the least derived base belonging to this vftable. - CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, - Info->PathToBaseWithVPtr.back()); + if (!CGM.IsBitSetBlacklistedRecord(Info->PathToBaseWithVPtr.back())) + CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, + Info->PathToBaseWithVPtr.back()); // Add a bitset entry for each derived class that is laid out at the same // offset as the least derived base. @@ -1543,11 +1545,12 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, Offset = VBI->second.VBaseOffset; if (!Offset.isZero()) return; - CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD); + if (!CGM.IsBitSetBlacklistedRecord(DerivedRD)) + CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD); } // Finally do the same for the most derived class. - if (Info->FullOffsetInMDC.isZero()) + if (Info->FullOffsetInMDC.isZero() && !CGM.IsBitSetBlacklistedRecord(RD)) CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD); } @@ -1816,7 +1819,7 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, MicrosoftVTableContext::MethodVFTableLocation ML = CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); - if (CGM.getCodeGenOpts().PrepareForLTO) + if (CGM.NeedVTableBitSets()) CGF.EmitBitSetCodeForVCall(getClassAtVTableLocation(getContext(), GD, ML), VTable, Loc); diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index c63ff4be8a7..50a93a8d431 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -39,7 +39,6 @@ enum : SanitizerMask { TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI, TrappingDefault = CFI, - CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast, }; enum CoverageFeature { @@ -682,16 +681,6 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, TC.getCompilerRT(Args, "stats"))); addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register"); } - - // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is - // enabled. - if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() && - !Args.hasArg(options::OPT_fvisibility_EQ)) { - TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with) - << lastArgumentForMask(TC.getDriver(), Args, - Sanitizers.Mask & CFIClasses) - << "-fvisibility="; - } } SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index f0199aab274..74ac8070561 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -4429,6 +4429,32 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-ffunction-sections"); } + if (Args.hasFlag(options::OPT_fwhole_program_vtables, + options::OPT_fno_whole_program_vtables, false)) { + if (!D.isUsingLTO()) + D.Diag(diag::err_drv_argument_only_allowed_with) + << "-fwhole-program-vtables" + << "-flto"; + CmdArgs.push_back("-fwhole-program-vtables"); + + clang::SmallString<64> Path(D.ResourceDir); + llvm::sys::path::append(Path, "vtables_blacklist.txt"); + if (llvm::sys::fs::exists(Path)) { + SmallString<64> BlacklistOpt("-fwhole-program-vtables-blacklist="); + BlacklistOpt += Path.str(); + CmdArgs.push_back(Args.MakeArgString(BlacklistOpt)); + } + + for (const Arg *A : + Args.filtered(options::OPT_fwhole_program_vtables_blacklist_EQ)) { + A->claim(); + if (!llvm::sys::fs::exists(A->getValue())) + D.Diag(clang::diag::err_drv_no_such_file) << A->getValue(); + } + + Args.AddAllArgs(CmdArgs, options::OPT_fwhole_program_vtables_blacklist_EQ); + } + if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections, UseSeparateSections)) { CmdArgs.push_back("-fdata-sections"); @@ -5759,17 +5785,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(I->getFilename()); } - bool WholeProgramVTables = - Args.hasFlag(options::OPT_fwhole_program_vtables, - options::OPT_fno_whole_program_vtables, false); - if (WholeProgramVTables) { - if (!D.isUsingLTO()) - D.Diag(diag::err_drv_argument_only_allowed_with) - << "-fwhole-program-vtables" - << "-flto"; - CmdArgs.push_back("-fwhole-program-vtables"); - } - // Finally add the compile command to the compilation. if (Args.hasArg(options::OPT__SLASH_fallback) && Output.getType() == types::TY_Object && @@ -6033,13 +6048,11 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, if (Args.hasArg(options::OPT__SLASH_LDd)) CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_MT"); - CmdArgs.push_back("-flto-visibility-public-std"); FlagForCRT = "--dependent-lib=libcmt"; break; case options::OPT__SLASH_MTd: CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_MT"); - CmdArgs.push_back("-flto-visibility-public-std"); FlagForCRT = "--dependent-lib=libcmtd"; break; default: diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 4bef159f3bf..0c4d5c71d5c 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -482,7 +482,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info); Opts.EmitCodeView = Args.hasArg(OPT_gcodeview); Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables); - Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std); + Opts.WholeProgramVTablesBlacklistFiles = + Args.getAllArgValues(OPT_fwhole_program_vtables_blacklist_EQ); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); Opts.DebugExplicitImport = Triple.isPS4CPU(); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 9bf5fc9e36d..0ba9799d042 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -5749,9 +5749,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_InternalLinkage: handleInternalLinkageAttr(S, D, Attr); break; - case AttributeList::AT_LTOVisibilityPublic: - handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, Attr); - break; // Microsoft attributes: case AttributeList::AT_MSNoVTable: diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index e72847cb53d..6d10e71d727 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -148,3 +148,16 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/) VERBATIM) endif() endif() + +set(src "${CMAKE_CURRENT_SOURCE_DIR}/vtables_blacklist.txt") +set(dst "${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/vtables_blacklist.txt") +add_custom_command(OUTPUT ${dst} + DEPENDS ${src} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} + COMMENT "Copying vtables blacklist") +add_custom_target(vtables_blacklist DEPENDS ${dst}) +set_target_properties(vtables_blacklist PROPERTIES FOLDER "Misc") +if(TARGET clang) + add_dependencies(clang vtables_blacklist) +endif() +install(FILES ${src} DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}) diff --git a/runtime/vtables_blacklist.txt b/runtime/vtables_blacklist.txt new file mode 100644 index 00000000000..f2016428d80 --- /dev/null +++ b/runtime/vtables_blacklist.txt @@ -0,0 +1,8 @@ +# Standard library types. +type:std::* + +# The stdext namespace contains Microsoft standard library extensions. +type:stdext::* + +# Types with a uuid attribute, i.e. COM types. +type:attr:uuid diff --git a/test/CodeGenCXX/bitset-blacklist.cpp b/test/CodeGenCXX/bitset-blacklist.cpp new file mode 100644 index 00000000000..ed15e43ce93 --- /dev/null +++ b/test/CodeGenCXX/bitset-blacklist.cpp @@ -0,0 +1,32 @@ +// RUN: echo "type:attr:uuid" > %t.txt +// RUN: %clang_cc1 -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOUUID %s +// RUN: %clang_cc1 -fms-extensions -fwhole-program-vtables -fwhole-program-vtables-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOUUID %s +// RUN: echo "type:std::*" > %t.txt +// RUN: %clang_cc1 -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s +// RUN: %clang_cc1 -fms-extensions -fwhole-program-vtables -fwhole-program-vtables-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s + +struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) S1 { + virtual void f(); +}; + +namespace std { + +struct S2 { + virtual void f(); +}; + +} + +// CHECK: define{{.*}}s1f +// NOSTD: llvm.bitset.test +// NOUUID-NOT: llvm.bitset.test +void s1f(S1 *s1) { + s1->f(); +} + +// CHECK: define{{.*}}s2f +// NOSTD-NOT: llvm.bitset.test +// NOUUID: llvm.bitset.test +void s2f(std::S2 *s2) { + s2->f(); +} diff --git a/test/CodeGenCXX/bitset-inference.cpp b/test/CodeGenCXX/bitset-inference.cpp deleted file mode 100644 index d9528609ff2..00000000000 --- a/test/CodeGenCXX/bitset-inference.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -std=c++11 -fms-extensions -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=ITANIUM %s -// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -std=c++11 -fms-extensions -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=MS --check-prefix=MS-STD %s -// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -std=c++11 -fms-extensions -fwhole-program-vtables -flto-visibility-public-std -emit-llvm -o - %s | FileCheck --check-prefix=MS --check-prefix=MS-NOSTD %s - -struct C1 { - virtual void f(); -}; - -struct __attribute__((visibility("default"))) C2 { - virtual void f(); -}; - -struct __declspec(dllexport) C3 { - virtual void f(); -}; - -struct __declspec(dllimport) C4 { - virtual void f(); -}; - -struct [[clang::lto_visibility_public]] C5 { - virtual void f(); -}; - -struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) C6 { - virtual void f(); -}; - -namespace std { - -struct C7 { - virtual void f(); - struct C8 { - virtual void f(); - }; -}; - -} - -extern "C++" { - -namespace stdext { - -struct C9 { - virtual void f(); -}; - -} - -} - -namespace other { - -struct C10 { - virtual void f(); -}; - -} - -namespace { - -struct C11 { - virtual void f(); -}; - -} - -void f(C1 *c1, C2 *c2, C3 *c3, C4 *c4, C5 *c5, C6 *c6, std::C7 *c7, - std::C7::C8 *c8, stdext::C9 *c9, other::C10 *c10) { - // ITANIUM: bitset.test{{.*}}!"_ZTS2C1" - // MS: bitset.test{{.*}}!"?AUC1@@" - c1->f(); - // ITANIUM-NOT: bitset.test{{.*}}!"_ZTS2C2" - // MS: bitset.test{{.*}}!"?AUC2@@" - c2->f(); - // ITANIUM: bitset.test{{.*}}!"_ZTS2C3" - // MS-NOT: bitset.test{{.*}}!"?AUC3@@" - c3->f(); - // ITANIUM: bitset.test{{.*}}!"_ZTS2C4" - // MS-NOT: bitset.test{{.*}}!"?AUC4@@" - c4->f(); - // ITANIUM-NOT: bitset.test{{.*}}!"_ZTS2C5" - // MS-NOT: bitset.test{{.*}}!"?AUC5@@" - c5->f(); - // ITANIUM-NOT: bitset.test{{.*}}!"_ZTS2C6" - // MS-NOT: bitset.test{{.*}}!"?AUC6@@" - c6->f(); - // ITANIUM: bitset.test{{.*}}!"_ZTSSt2C7" - // MS-STD: bitset.test{{.*}}!"?AUC7@std@@" - // MS-NOSTD-NOT: bitset.test{{.*}}!"?AUC7@std@@" - c7->f(); - // ITANIUM: bitset.test{{.*}}!"_ZTSNSt2C72C8E" - // MS-STD: bitset.test{{.*}}!"?AUC8@C7@std@@" - // MS-NOSTD-NOT: bitset.test{{.*}}!"?AUC8@C7@std@@" - c8->f(); - // ITANIUM: bitset.test{{.*}}!"_ZTSN6stdext2C9E" - // MS-STD: bitset.test{{.*}}!"?AUC9@stdext@@" - // MS-NOSTD-NOT: bitset.test{{.*}}!"?AUC9@stdext@@" - c9->f(); - // ITANIUM: bitset.test{{.*}}!"_ZTSN5other3C10E" - // MS: bitset.test{{.*}}!"?AUC10@other@@" - c10->f(); - // ITANIUM: bitset.test{{.*}}!{{[0-9]}} - // MS: bitset.test{{.*}}!{{[0-9]}} - C11 *c11; - c11->f(); -} diff --git a/test/CodeGenCXX/bitsets.cpp b/test/CodeGenCXX/bitsets.cpp index 4d11f39b66b..dba399cc96f 100644 --- a/test/CodeGenCXX/bitsets.cpp +++ b/test/CodeGenCXX/bitsets.cpp @@ -1,12 +1,12 @@ // Tests for the cfi-vcall feature: -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-NDIAG --check-prefix=NDIAG %s -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-ABORT %s -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s -// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=MS --check-prefix=NDIAG %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-NDIAG --check-prefix=NDIAG %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-ABORT %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=MS --check-prefix=NDIAG %s // Tests for the whole-program-vtables feature: -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM %s -// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=MS %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=MS %s // MS: @[[VTA:[0-9]*]] {{.*}} comdat($"\01??_7A@@6B@") // MS: @[[VTB:[0-9]*]] {{.*}} comdat($"\01??_7B@@6B0@@") @@ -62,7 +62,7 @@ void D::h() { // DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" } // DIAG: @[[BADTYPESTATIC:.*]] = private unnamed_addr global { i8, { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }* } { i8 0, { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 [[@LINE+24]], i32 3 }, { i16, i16, [4 x i8] }* @[[TYPE]] } -// ITANIUM: define hidden void @_Z2afP1A +// ITANIUM: define void @_Z2afP1A // MS: define void @"\01?af@@YAXPEAUA@@@Z" void af(A *a) { // ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A") @@ -155,7 +155,7 @@ struct D : C { void m_fn1(); }; -// ITANIUM: define hidden void @_ZN5test21fEPNS_1DE +// ITANIUM: define void @_ZN5test21fEPNS_1DE // MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z" void f(D *d) { // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE") diff --git a/test/CodeGenCXX/cfi-blacklist.cpp b/test/CodeGenCXX/cfi-blacklist.cpp deleted file mode 100644 index 38b9971c90e..00000000000 --- a/test/CodeGenCXX/cfi-blacklist.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s -// RUN: echo "type:std::*" > %t.txt -// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s - -struct S1 { - virtual void f(); -}; - -namespace std { - -struct S2 { - virtual void f(); -}; - -} - -// CHECK: define{{.*}}s1f -// NOBL: llvm.bitset.test -// NOSTD: llvm.bitset.test -void s1f(S1 *s1) { - s1->f(); -} - -// CHECK: define{{.*}}s2f -// NOBL: llvm.bitset.test -// NOSTD-NOT: llvm.bitset.test -void s2f(std::S2 *s2) { - s2->f(); -} diff --git a/test/CodeGenCXX/cfi-cast.cpp b/test/CodeGenCXX/cfi-cast.cpp index 9fe87111b38..7935b7364c6 100644 --- a/test/CodeGenCXX/cfi-cast.cpp +++ b/test/CodeGenCXX/cfi-cast.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -std=c++11 -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-DCAST %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -std=c++11 -fsanitize=cfi-unrelated-cast -fsanitize-trap=cfi-unrelated-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -std=c++11 -fsanitize=cfi-unrelated-cast,cfi-cast-strict -fsanitize-trap=cfi-unrelated-cast,cfi-cast-strict -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST-STRICT %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -std=c++11 -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-DCAST %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -std=c++11 -fsanitize=cfi-unrelated-cast -fsanitize-trap=cfi-unrelated-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -std=c++11 -fsanitize=cfi-unrelated-cast,cfi-cast-strict -fsanitize-trap=cfi-unrelated-cast,cfi-cast-strict -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST-STRICT %s // In this test the main thing we are searching for is something like // 'metadata !"1B"' where "1B" is the mangled name of the class we are @@ -17,7 +17,7 @@ struct B : A { struct C : A {}; -// CHECK-DCAST-LABEL: define hidden void @_Z3abpP1A +// CHECK-DCAST-LABEL: define void @_Z3abpP1A void abp(A *a) { // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] @@ -31,7 +31,7 @@ void abp(A *a) { (void)static_cast<B*>(a); } -// CHECK-DCAST-LABEL: define hidden void @_Z3abrR1A +// CHECK-DCAST-LABEL: define void @_Z3abrR1A void abr(A &a) { // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] @@ -45,7 +45,7 @@ void abr(A &a) { (void)static_cast<B&>(a); } -// CHECK-DCAST-LABEL: define hidden void @_Z4abrrO1A +// CHECK-DCAST-LABEL: define void @_Z4abrrO1A void abrr(A &&a) { // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] @@ -59,7 +59,7 @@ void abrr(A &&a) { (void)static_cast<B&&>(a); } -// CHECK-UCAST-LABEL: define hidden void @_Z3vbpPv +// CHECK-UCAST-LABEL: define void @_Z3vbpPv void vbp(void *p) { // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] @@ -73,7 +73,7 @@ void vbp(void *p) { (void)static_cast<B*>(p); } -// CHECK-UCAST-LABEL: define hidden void @_Z3vbrRc +// CHECK-UCAST-LABEL: define void @_Z3vbrRc void vbr(char &r) { // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] @@ -87,7 +87,7 @@ void vbr(char &r) { (void)reinterpret_cast<B&>(r); } -// CHECK-UCAST-LABEL: define hidden void @_Z4vbrrOc +// CHECK-UCAST-LABEL: define void @_Z4vbrrOc void vbrr(char &&r) { // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] @@ -101,32 +101,32 @@ void vbrr(char &&r) { (void)reinterpret_cast<B&&>(r); } -// CHECK-UCAST-LABEL: define hidden void @_Z3vcpPv -// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3vcpPv +// CHECK-UCAST-LABEL: define void @_Z3vcpPv +// CHECK-UCAST-STRICT-LABEL: define void @_Z3vcpPv void vcp(void *p) { // CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") // CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") (void)static_cast<C*>(p); } -// CHECK-UCAST-LABEL: define hidden void @_Z3bcpP1B -// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3bcpP1B +// CHECK-UCAST-LABEL: define void @_Z3bcpP1B +// CHECK-UCAST-STRICT-LABEL: define void @_Z3bcpP1B void bcp(B *p) { // CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") // CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") (void)(C *)p; } -// CHECK-UCAST-LABEL: define hidden void @_Z8bcp_callP1B -// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z8bcp_callP1B +// CHECK-UCAST-LABEL: define void @_Z8bcp_callP1B +// CHECK-UCAST-STRICT-LABEL: define void @_Z8bcp_callP1B void bcp_call(B *p) { // CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") // CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") ((C *)p)->f(); } -// CHECK-UCAST-LABEL: define hidden i32 @_Z6a_callP1A -// CHECK-UCAST-STRICT-LABEL: define hidden i32 @_Z6a_callP1A +// CHECK-UCAST-LABEL: define i32 @_Z6a_callP1A +// CHECK-UCAST-STRICT-LABEL: define i32 @_Z6a_callP1A int a_call(A *a) { // CHECK-UCAST-NOT: @llvm.bitset.test // CHECK-UCAST-STRICT-NOT: @llvm.bitset.test diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp index 84a6879e55f..edcbb783ccd 100644 --- a/test/CodeGenCXX/cfi-cross-dso.cpp +++ b/test/CodeGenCXX/cfi-cross-dso.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM %s -// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s struct A { A(); diff --git a/test/CodeGenCXX/cfi-ms-rtti.cpp b/test/CodeGenCXX/cfi-ms-rtti.cpp index 12c9868ceee..b6e9175c865 100644 --- a/test/CodeGenCXX/cfi-ms-rtti.cpp +++ b/test/CodeGenCXX/cfi-ms-rtti.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -flto -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall | FileCheck --check-prefix=RTTI %s -// RUN: %clang_cc1 -flto -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall -fno-rtti-data | FileCheck --check-prefix=NO-RTTI %s +// RUN: %clang_cc1 -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall | FileCheck --check-prefix=RTTI %s +// RUN: %clang_cc1 -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall -fno-rtti-data | FileCheck --check-prefix=NO-RTTI %s struct A { A(); diff --git a/test/CodeGenCXX/cfi-nvcall.cpp b/test/CodeGenCXX/cfi-nvcall.cpp index ea18e216f07..be4d8448a2e 100644 --- a/test/CodeGenCXX/cfi-nvcall.cpp +++ b/test/CodeGenCXX/cfi-nvcall.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-nvcall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-nvcall,cfi-cast-strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-STRICT %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-nvcall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-nvcall,cfi-cast-strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-STRICT %s struct A { virtual void f(); diff --git a/test/CodeGenCXX/cfi-stats.cpp b/test/CodeGenCXX/cfi-stats.cpp index e6421321edd..aac71634d0d 100644 --- a/test/CodeGenCXX/cfi-stats.cpp +++ b/test/CodeGenCXX/cfi-stats.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall,cfi-nvcall,cfi-derived-cast,cfi-unrelated-cast,cfi-icall -fsanitize-stats -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall,cfi-nvcall,cfi-derived-cast,cfi-unrelated-cast,cfi-icall -fsanitize-stats -emit-llvm -o - %s | FileCheck %s // CHECK: [[STATS:@[^ ]*]] = internal global { i8*, i32, [5 x [2 x i8*]] } { i8* null, i32 5, [5 x [2 x i8*]] // CHECK: {{\[\[}}2 x i8*] zeroinitializer, diff --git a/test/Driver/cl-runtime-flags.c b/test/Driver/cl-runtime-flags.c index 3fa036d2019..a54aa1a14ae 100644 --- a/test/Driver/cl-runtime-flags.c +++ b/test/Driver/cl-runtime-flags.c @@ -13,7 +13,6 @@ // CHECK-MT-NOT: "-D_DEBUG" // CHECK-MT: "-D_MT" // CHECK-MT-NOT: "-D_DLL" -// CHECK-MT: "-flto-visibility-public-std" // CHECK-MT: "--dependent-lib=libcmt" // CHECK-MT: "--dependent-lib=oldnames" @@ -22,7 +21,6 @@ // CHECK-MTd: "-D_DEBUG" // CHECK-MTd: "-D_MT" // CHECK-MTd-NOT: "-D_DLL" -// CHECK-MTd: "-flto-visibility-public-std" // CHECK-MTd: "--dependent-lib=libcmtd" // CHECK-MTd: "--dependent-lib=oldnames" diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 40cd49525ef..7c1b9be793a 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -291,29 +291,21 @@ -// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI -// RUN: %clang -target x86_64-apple-darwin10 -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI -// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi-derived-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-DCAST -// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi-unrelated-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-UCAST -// RUN: %clang -target x86_64-linux-gnu -flto -fvisibility=hidden -fsanitize=cfi-nvcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NVCALL -// RUN: %clang -target x86_64-linux-gnu -flto -fvisibility=hidden -fsanitize=cfi-vcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-VCALL +// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI +// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-derived-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-DCAST +// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-unrelated-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-UCAST +// RUN: %clang -target x86_64-linux-gnu -flto -fsanitize=cfi-nvcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NVCALL +// RUN: %clang -target x86_64-linux-gnu -flto -fsanitize=cfi-vcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-VCALL // CHECK-CFI: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall // CHECK-CFI-DCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast // CHECK-CFI-UCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-unrelated-cast // CHECK-CFI-NVCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-nvcall // CHECK-CFI-VCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-vcall -// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -flto -fsanitize=cfi-derived-cast -fno-lto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOLTO +// RUN: %clang -target x86_64-linux-gnu -flto -fsanitize=cfi-derived-cast -fno-lto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOLTO // CHECK-CFI-NOLTO: '-fsanitize=cfi-derived-cast' only allowed with '-flto' -// RUN: %clang -target x86_64-linux-gnu -flto -fsanitize=cfi-derived-cast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOVIS -// CHECK-CFI-NOVIS: '-fsanitize=cfi-derived-cast' only allowed with '-fvisibility=' - -// RUN: %clang -target x86_64-pc-win32 -flto -fsanitize=cfi-derived-cast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOVIS-NOERROR -// RUN: echo > %t.o -// RUN: %clang -target x86_64-linux-gnu -flto -fsanitize=cfi-derived-cast %t.o -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOVIS-NOERROR -// CHECK-CFI-NOVIS-NOERROR-NOT: only allowed with - // RUN: %clang -target mips-unknown-linux -fsanitize=cfi-icall %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-ICALL-MIPS // CHECK-CFI-ICALL-MIPS: unsupported option '-fsanitize=cfi-icall' for target 'mips-unknown-linux' diff --git a/test/Driver/whole-program-vtables.c b/test/Driver/whole-program-vtables.c index 4ca985e6d71..99f6f4c8b13 100644 --- a/test/Driver/whole-program-vtables.c +++ b/test/Driver/whole-program-vtables.c @@ -1,2 +1,11 @@ // RUN: %clang -target x86_64-unknown-linux -fwhole-program-vtables -### %s 2>&1 | FileCheck --check-prefix=NO-LTO %s // NO-LTO: invalid argument '-fwhole-program-vtables' only allowed with '-flto' + +// RUN: %clang -target x86_64-unknown-linux -resource-dir=%S/Inputs/resource_dir -flto -fwhole-program-vtables -### -c %s 2>&1 | FileCheck --check-prefix=BLACKLIST %s +// BLACKLIST: "-fwhole-program-vtables-blacklist={{.*}}vtables_blacklist.txt" + +// RUN: %clang -target x86_64-unknown-linux -fwhole-program-vtables-blacklist=nonexistent.txt -flto -fwhole-program-vtables -### -c %s 2>&1 | FileCheck --check-prefix=NON-EXISTENT-BLACKLIST %s +// NON-EXISTENT-BLACKLIST: no such file or directory: 'nonexistent.txt' + +// RUN: %clang -target x86_64-unknown-linux -fwhole-program-vtables-blacklist=%S/Inputs/resource_dir/vtables_blacklist.txt -flto -fwhole-program-vtables -### -c %s 2>&1 | FileCheck --check-prefix=CUSTOM-BLACKLIST %s +// CUSTOM-BLACKLIST: "-fwhole-program-vtables-blacklist={{.*}}Inputs/resource_dir/vtables_blacklist.txt" diff --git a/test/Frontend/dependency-gen.c b/test/Frontend/dependency-gen.c index e4b0feea16a..054aa79e3d4 100644 --- a/test/Frontend/dependency-gen.c +++ b/test/Frontend/dependency-gen.c @@ -21,7 +21,7 @@ // RUN: %clang -MD -MF - %s -fsyntax-only -I ./ | FileCheck -check-prefix=CHECK-SIX %s // CHECK-SIX: {{ }}x.h // RUN: echo "fun:foo" > %t.blacklist -// RUN: %clang -MD -MF - %s -fsyntax-only -fsanitize=cfi-vcall -flto -fvisibility=hidden -fsanitize-blacklist=%t.blacklist -I ./ | FileCheck -check-prefix=CHECK-SEVEN %s +// RUN: %clang -MD -MF - %s -fsyntax-only -fsanitize=cfi-vcall -flto -fsanitize-blacklist=%t.blacklist -I ./ | FileCheck -check-prefix=CHECK-SEVEN %s // CHECK-SEVEN: .blacklist // CHECK-SEVEN: {{ }}x.h #ifndef INCLUDE_FLAG_TEST diff --git a/test/SemaCXX/attr-lto-visibility-public.cpp b/test/SemaCXX/attr-lto-visibility-public.cpp deleted file mode 100644 index 2f9ed87f6ee..00000000000 --- a/test/SemaCXX/attr-lto-visibility-public.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s - -int i [[clang::lto_visibility_public]]; // expected-warning {{'lto_visibility_public' attribute only applies to struct, union or class}} -typedef int t [[clang::lto_visibility_public]]; // expected-warning {{'lto_visibility_public' attribute only applies to struct, union or class}} -[[clang::lto_visibility_public]] void f(); // expected-warning {{'lto_visibility_public' attribute only applies to struct, union or class}} -void f() [[clang::lto_visibility_public]]; // expected-error {{'lto_visibility_public' attribute cannot be applied to types}} - -struct [[clang::lto_visibility_public]] s1 { - int i [[clang::lto_visibility_public]]; // expected-warning {{'lto_visibility_public' attribute only applies to struct, union or class}} - [[clang::lto_visibility_public]] void f(); // expected-warning {{'lto_visibility_public' attribute only applies to struct, union or class}} -}; - -struct [[clang::lto_visibility_public(1)]] s2 { // expected-error {{'lto_visibility_public' attribute takes no arguments}} -}; -- GitLab