forked from OSchip/llvm-project
Re-apply r267784, r267824 and r267830.
I have updated the compiler-rt tests. llvm-svn: 267903
This commit is contained in:
parent
f730de619f
commit
3afb266886
clang
docs
include/clang
lib
CodeGen
Driver
Frontend
Sema
runtime
test
|
@ -25,13 +25,25 @@ 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,
|
so it is required to specify ``-flto``, and the linker used must support LTO,
|
||||||
for example via the `gold plugin`_.
|
for example via the `gold plugin`_.
|
||||||
|
|
||||||
To allow the checks to be implemented efficiently, the program must be
|
To allow the checks to be implemented efficiently, the program must
|
||||||
structured such that certain object files are compiled with CFI
|
be structured such that certain object files are compiled with CFI
|
||||||
enabled, and are statically linked into the program. This may preclude
|
enabled, and are statically linked into the program. This may preclude
|
||||||
the use of shared libraries in some cases. Experimental support for
|
the use of shared libraries in some cases.
|
||||||
:ref:`cross-DSO control flow integrity <cfi-cross-dso>` exists that
|
|
||||||
does not have these requirements. This cross-DSO support has unstable
|
The compiler will only produce CFI checks for a class if it can infer hidden
|
||||||
ABI at this time.
|
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.
|
||||||
|
|
||||||
.. _gold plugin: http://llvm.org/docs/GoldPlugin.html
|
.. _gold plugin: http://llvm.org/docs/GoldPlugin.html
|
||||||
|
|
||||||
|
@ -233,11 +245,6 @@ A :doc:`SanitizerSpecialCaseList` can be used to relax CFI checks for certain
|
||||||
source files, functions and types using the ``src``, ``fun`` and ``type``
|
source files, functions and types using the ``src``, ``fun`` and ``type``
|
||||||
entity types.
|
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
|
.. code-block:: bash
|
||||||
|
|
||||||
# Suppress checking for code in a file.
|
# Suppress checking for code in a file.
|
||||||
|
@ -247,8 +254,6 @@ are typically defined outside of the linked program.
|
||||||
fun:*MyFooBar*
|
fun:*MyFooBar*
|
||||||
# Ignore all types in the standard library.
|
# Ignore all types in the standard library.
|
||||||
type:std::*
|
type:std::*
|
||||||
# Ignore all types with a uuid attribute.
|
|
||||||
type:attr:uuid
|
|
||||||
|
|
||||||
.. _cfi-cross-dso:
|
.. _cfi-cross-dso:
|
||||||
|
|
||||||
|
@ -260,6 +265,11 @@ flow integrity mode, which allows all CFI schemes listed above to
|
||||||
apply across DSO boundaries. As in the regular CFI, each DSO must be
|
apply across DSO boundaries. As in the regular CFI, each DSO must be
|
||||||
built with ``-flto``.
|
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
|
Design
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
==============
|
||||||
|
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``.
|
|
@ -1056,17 +1056,8 @@ are listed below.
|
||||||
.. option:: -fwhole-program-vtables
|
.. option:: -fwhole-program-vtables
|
||||||
|
|
||||||
Enable whole-program vtable optimizations, such as single-implementation
|
Enable whole-program vtable optimizations, such as single-implementation
|
||||||
devirtualization and virtual constant propagation. Requires ``-flto``.
|
devirtualization and virtual constant propagation, for classes with
|
||||||
|
:doc:`hidden LTO visibility <LTOVisibility>`. 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
|
.. option:: -fno-assume-sane-operator-new
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ Using Clang as a Compiler
|
||||||
SanitizerStats
|
SanitizerStats
|
||||||
SanitizerSpecialCaseList
|
SanitizerSpecialCaseList
|
||||||
ControlFlowIntegrity
|
ControlFlowIntegrity
|
||||||
|
LTOVisibility
|
||||||
SafeStack
|
SafeStack
|
||||||
Modules
|
Modules
|
||||||
MSVCCompatibility
|
MSVCCompatibility
|
||||||
|
|
|
@ -1611,6 +1611,12 @@ def WeakRef : InheritableAttr {
|
||||||
let Documentation = [Undocumented];
|
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> {
|
def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
|
||||||
// NOTE: If you add any additional spellings, ARMInterrupt's,
|
// NOTE: If you add any additional spellings, ARMInterrupt's,
|
||||||
// MSP430Interrupt's and MipsInterrupt's spellings must match.
|
// MSP430Interrupt's and MipsInterrupt's spellings must match.
|
||||||
|
|
|
@ -2380,3 +2380,10 @@ 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.
|
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`.
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
|
@ -282,6 +282,9 @@ def fprofile_instrument_path_EQ : Joined<["-"], "fprofile-instrument-path=">,
|
||||||
def fprofile_instrument_use_path_EQ :
|
def fprofile_instrument_use_path_EQ :
|
||||||
Joined<["-"], "fprofile-instrument-use-path=">,
|
Joined<["-"], "fprofile-instrument-use-path=">,
|
||||||
HelpText<"Specify the profile path in PGO use compilation">;
|
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
|
// Dependency Output Options
|
||||||
|
|
|
@ -1152,9 +1152,6 @@ def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Grou
|
||||||
Flags<[CC1Option]>,
|
Flags<[CC1Option]>,
|
||||||
HelpText<"Enables whole-program vtable optimization. Requires -flto">;
|
HelpText<"Enables whole-program vtable optimization. Requires -flto">;
|
||||||
def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>;
|
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]>,
|
def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
|
||||||
HelpText<"Treat signed integer overflow as two's complement">;
|
HelpText<"Treat signed integer overflow as two's complement">;
|
||||||
def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
|
def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
|
||||||
|
|
|
@ -187,6 +187,10 @@ CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
|
||||||
CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program
|
CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program
|
||||||
/// vtable optimization.
|
/// 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,
|
/// The user specified number of registers to be used for integral arguments,
|
||||||
/// or 0 if unspecified.
|
/// or 0 if unspecified.
|
||||||
VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
|
VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
|
||||||
|
|
|
@ -199,9 +199,6 @@ public:
|
||||||
/// \brief A list of all -fno-builtin-* function names (e.g., memset).
|
/// \brief A list of all -fno-builtin-* function names (e.g., memset).
|
||||||
std::vector<std::string> NoBuiltinFuncs;
|
std::vector<std::string> NoBuiltinFuncs;
|
||||||
|
|
||||||
/// List of blacklist files for the whole-program vtable optimization feature.
|
|
||||||
std::vector<std::string> WholeProgramVTablesBlacklistFiles;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Define accessors/mutators for code generation options of enumeration type.
|
// Define accessors/mutators for code generation options of enumeration type.
|
||||||
#define CODEGENOPT(Name, Bits, Default)
|
#define CODEGENOPT(Name, Bits, Default)
|
||||||
|
|
|
@ -2489,7 +2489,7 @@ void CodeGenFunction::EmitBitSetCodeForVCall(const CXXRecordDecl *RD,
|
||||||
llvm::Value *VTable,
|
llvm::Value *VTable,
|
||||||
SourceLocation Loc) {
|
SourceLocation Loc) {
|
||||||
if (CGM.getCodeGenOpts().WholeProgramVTables &&
|
if (CGM.getCodeGenOpts().WholeProgramVTables &&
|
||||||
!CGM.IsBitSetBlacklistedRecord(RD)) {
|
CGM.HasHiddenLTOVisibility(RD)) {
|
||||||
llvm::Metadata *MD =
|
llvm::Metadata *MD =
|
||||||
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
|
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
|
||||||
llvm::Value *BitSetName =
|
llvm::Value *BitSetName =
|
||||||
|
@ -2565,7 +2565,12 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
|
||||||
llvm::Value *VTable,
|
llvm::Value *VTable,
|
||||||
CFITypeCheckKind TCK,
|
CFITypeCheckKind TCK,
|
||||||
SourceLocation Loc) {
|
SourceLocation Loc) {
|
||||||
if (CGM.IsBitSetBlacklistedRecord(RD))
|
if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso &&
|
||||||
|
!CGM.HasHiddenLTOVisibility(RD))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string TypeName = RD->getQualifiedNameAsString();
|
||||||
|
if (getContext().getSanitizerBlacklist().isBlacklistedType(TypeName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SanitizerScope SanScope(this);
|
SanitizerScope SanScope(this);
|
||||||
|
|
|
@ -902,34 +902,43 @@ void CodeGenModule::EmitDeferredVTables() {
|
||||||
DeferredVTables.clear();
|
DeferredVTables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CodeGenModule::NeedVTableBitSets() {
|
bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
|
||||||
return getCodeGenOpts().WholeProgramVTables ||
|
LinkageInfo LV = RD->getLinkageAndVisibility();
|
||||||
getLangOpts().Sanitize.has(SanitizerKind::CFIVCall) ||
|
if (!isExternallyVisible(LV.getLinkage()))
|
||||||
getLangOpts().Sanitize.has(SanitizerKind::CFINVCall) ||
|
return true;
|
||||||
getLangOpts().Sanitize.has(SanitizerKind::CFIDerivedCast) ||
|
|
||||||
getLangOpts().Sanitize.has(SanitizerKind::CFIUnrelatedCast);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CodeGenModule::IsBitSetBlacklistedRecord(const CXXRecordDecl *RD) {
|
if (RD->hasAttr<LTOVisibilityPublicAttr>() || RD->hasAttr<UuidAttr>())
|
||||||
std::string TypeName = RD->getQualifiedNameAsString();
|
return false;
|
||||||
auto isInBlacklist = [&](const SanitizerBlacklist &BL) {
|
|
||||||
if (RD->hasAttr<UuidAttr>() && BL.isBlacklistedType("attr:uuid"))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return BL.isBlacklistedType(TypeName);
|
if (getTriple().isOSBinFormatCOFF()) {
|
||||||
};
|
if (RD->hasAttr<DLLExportAttr>() || RD->hasAttr<DLLImportAttr>())
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (LV.getVisibility() != HiddenVisibility)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return isInBlacklist(WholeProgramVTablesBlacklist) ||
|
if (getCodeGenOpts().LTOVisibilityPublicStd) {
|
||||||
((LangOpts.Sanitize.has(SanitizerKind::CFIVCall) ||
|
const DeclContext *DC = RD;
|
||||||
LangOpts.Sanitize.has(SanitizerKind::CFINVCall) ||
|
while (1) {
|
||||||
LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) ||
|
auto *D = cast<Decl>(DC);
|
||||||
LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast)) &&
|
DC = DC->getParent();
|
||||||
isInBlacklist(getContext().getSanitizerBlacklist()));
|
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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
|
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
|
||||||
const VTableLayout &VTLayout) {
|
const VTableLayout &VTLayout) {
|
||||||
if (!NeedVTableBitSets())
|
if (!getCodeGenOpts().PrepareForLTO)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CharUnits PointerWidth =
|
CharUnits PointerWidth =
|
||||||
|
@ -938,12 +947,8 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
|
||||||
typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry;
|
typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry;
|
||||||
std::vector<BSEntry> BitsetEntries;
|
std::vector<BSEntry> BitsetEntries;
|
||||||
// Create a bit set entry for each address point.
|
// 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));
|
BitsetEntries.push_back(std::make_pair(AP.first.getBase(), AP.second));
|
||||||
}
|
|
||||||
|
|
||||||
// Sort the bit set entries for determinism.
|
// Sort the bit set entries for determinism.
|
||||||
std::sort(BitsetEntries.begin(), BitsetEntries.end(),
|
std::sort(BitsetEntries.begin(), BitsetEntries.end(),
|
||||||
|
|
|
@ -88,9 +88,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
|
||||||
PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags),
|
PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags),
|
||||||
Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
|
Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
|
||||||
VMContext(M.getContext()), Types(*this), VTables(*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.
|
// Initialize the type cache.
|
||||||
llvm::LLVMContext &LLVMContext = M.getContext();
|
llvm::LLVMContext &LLVMContext = M.getContext();
|
||||||
|
|
|
@ -490,8 +490,6 @@ private:
|
||||||
/// MDNodes.
|
/// MDNodes.
|
||||||
llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
|
llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
|
||||||
|
|
||||||
SanitizerBlacklist WholeProgramVTablesBlacklist;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
|
CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
|
||||||
const PreprocessorOptions &ppopts,
|
const PreprocessorOptions &ppopts,
|
||||||
|
@ -1115,12 +1113,10 @@ public:
|
||||||
void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D,
|
void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D,
|
||||||
CodeGenFunction *CGF = nullptr);
|
CodeGenFunction *CGF = nullptr);
|
||||||
|
|
||||||
/// Returns whether we need bit sets attached to vtables.
|
/// Returns whether the given record has hidden LTO visibility and therefore
|
||||||
bool NeedVTableBitSets();
|
/// may participate in (single-module) CFI and whole-program vtable
|
||||||
|
/// optimization.
|
||||||
/// Returns whether the given record is blacklisted from whole-program
|
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD);
|
||||||
/// 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
|
/// Emit bit set entries for the given vtable using the given layout if
|
||||||
/// vptr CFI is enabled.
|
/// vptr CFI is enabled.
|
||||||
|
|
|
@ -1503,7 +1503,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
|
||||||
void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
|
void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
|
||||||
const CXXRecordDecl *RD,
|
const CXXRecordDecl *RD,
|
||||||
llvm::GlobalVariable *VTable) {
|
llvm::GlobalVariable *VTable) {
|
||||||
if (!CGM.NeedVTableBitSets())
|
if (!CGM.getCodeGenOpts().PrepareForLTO)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
llvm::NamedMDNode *BitsetsMD =
|
llvm::NamedMDNode *BitsetsMD =
|
||||||
|
@ -1519,15 +1519,13 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
|
||||||
: CharUnits::Zero();
|
: CharUnits::Zero();
|
||||||
|
|
||||||
if (Info->PathToBaseWithVPtr.empty()) {
|
if (Info->PathToBaseWithVPtr.empty()) {
|
||||||
if (!CGM.IsBitSetBlacklistedRecord(RD))
|
CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD);
|
||||||
CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a bitset entry for the least derived base belonging to this vftable.
|
// Add a bitset entry for the least derived base belonging to this vftable.
|
||||||
if (!CGM.IsBitSetBlacklistedRecord(Info->PathToBaseWithVPtr.back()))
|
CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint,
|
||||||
CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint,
|
Info->PathToBaseWithVPtr.back());
|
||||||
Info->PathToBaseWithVPtr.back());
|
|
||||||
|
|
||||||
// Add a bitset entry for each derived class that is laid out at the same
|
// Add a bitset entry for each derived class that is laid out at the same
|
||||||
// offset as the least derived base.
|
// offset as the least derived base.
|
||||||
|
@ -1545,12 +1543,11 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
|
||||||
Offset = VBI->second.VBaseOffset;
|
Offset = VBI->second.VBaseOffset;
|
||||||
if (!Offset.isZero())
|
if (!Offset.isZero())
|
||||||
return;
|
return;
|
||||||
if (!CGM.IsBitSetBlacklistedRecord(DerivedRD))
|
CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD);
|
||||||
CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally do the same for the most derived class.
|
// Finally do the same for the most derived class.
|
||||||
if (Info->FullOffsetInMDC.isZero() && !CGM.IsBitSetBlacklistedRecord(RD))
|
if (Info->FullOffsetInMDC.isZero())
|
||||||
CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD);
|
CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1819,7 +1816,7 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
|
||||||
|
|
||||||
MicrosoftVTableContext::MethodVFTableLocation ML =
|
MicrosoftVTableContext::MethodVFTableLocation ML =
|
||||||
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
|
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
|
||||||
if (CGM.NeedVTableBitSets())
|
if (CGM.getCodeGenOpts().PrepareForLTO)
|
||||||
CGF.EmitBitSetCodeForVCall(getClassAtVTableLocation(getContext(), GD, ML),
|
CGF.EmitBitSetCodeForVCall(getClassAtVTableLocation(getContext(), GD, ML),
|
||||||
VTable, Loc);
|
VTable, Loc);
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ enum : SanitizerMask {
|
||||||
TrappingSupported =
|
TrappingSupported =
|
||||||
(Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
|
(Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
|
||||||
TrappingDefault = CFI,
|
TrappingDefault = CFI,
|
||||||
|
CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CoverageFeature {
|
enum CoverageFeature {
|
||||||
|
@ -681,6 +682,16 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
|
||||||
TC.getCompilerRT(Args, "stats")));
|
TC.getCompilerRT(Args, "stats")));
|
||||||
addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
|
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,
|
SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
|
||||||
|
|
|
@ -4429,32 +4429,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
CmdArgs.push_back("-ffunction-sections");
|
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,
|
if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
|
||||||
UseSeparateSections)) {
|
UseSeparateSections)) {
|
||||||
CmdArgs.push_back("-fdata-sections");
|
CmdArgs.push_back("-fdata-sections");
|
||||||
|
@ -5785,6 +5759,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
CmdArgs.push_back(I->getFilename());
|
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.
|
// Finally add the compile command to the compilation.
|
||||||
if (Args.hasArg(options::OPT__SLASH_fallback) &&
|
if (Args.hasArg(options::OPT__SLASH_fallback) &&
|
||||||
Output.getType() == types::TY_Object &&
|
Output.getType() == types::TY_Object &&
|
||||||
|
@ -6048,11 +6033,13 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
|
||||||
if (Args.hasArg(options::OPT__SLASH_LDd))
|
if (Args.hasArg(options::OPT__SLASH_LDd))
|
||||||
CmdArgs.push_back("-D_DEBUG");
|
CmdArgs.push_back("-D_DEBUG");
|
||||||
CmdArgs.push_back("-D_MT");
|
CmdArgs.push_back("-D_MT");
|
||||||
|
CmdArgs.push_back("-flto-visibility-public-std");
|
||||||
FlagForCRT = "--dependent-lib=libcmt";
|
FlagForCRT = "--dependent-lib=libcmt";
|
||||||
break;
|
break;
|
||||||
case options::OPT__SLASH_MTd:
|
case options::OPT__SLASH_MTd:
|
||||||
CmdArgs.push_back("-D_DEBUG");
|
CmdArgs.push_back("-D_DEBUG");
|
||||||
CmdArgs.push_back("-D_MT");
|
CmdArgs.push_back("-D_MT");
|
||||||
|
CmdArgs.push_back("-flto-visibility-public-std");
|
||||||
FlagForCRT = "--dependent-lib=libcmtd";
|
FlagForCRT = "--dependent-lib=libcmtd";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -482,8 +482,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
||||||
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
|
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
|
||||||
Opts.EmitCodeView = Args.hasArg(OPT_gcodeview);
|
Opts.EmitCodeView = Args.hasArg(OPT_gcodeview);
|
||||||
Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
|
Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
|
||||||
Opts.WholeProgramVTablesBlacklistFiles =
|
Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std);
|
||||||
Args.getAllArgValues(OPT_fwhole_program_vtables_blacklist_EQ);
|
|
||||||
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
|
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
|
||||||
Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
|
Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
|
||||||
Opts.DebugExplicitImport = Triple.isPS4CPU();
|
Opts.DebugExplicitImport = Triple.isPS4CPU();
|
||||||
|
|
|
@ -5749,6 +5749,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
||||||
case AttributeList::AT_InternalLinkage:
|
case AttributeList::AT_InternalLinkage:
|
||||||
handleInternalLinkageAttr(S, D, Attr);
|
handleInternalLinkageAttr(S, D, Attr);
|
||||||
break;
|
break;
|
||||||
|
case AttributeList::AT_LTOVisibilityPublic:
|
||||||
|
handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, Attr);
|
||||||
|
break;
|
||||||
|
|
||||||
// Microsoft attributes:
|
// Microsoft attributes:
|
||||||
case AttributeList::AT_MSNoVTable:
|
case AttributeList::AT_MSNoVTable:
|
||||||
|
|
|
@ -148,16 +148,3 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/)
|
||||||
VERBATIM)
|
VERBATIM)
|
||||||
endif()
|
endif()
|
||||||
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})
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# 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
|
|
|
@ -1,32 +0,0 @@
|
||||||
// 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();
|
|
||||||
}
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
// 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();
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
// Tests for the cfi-vcall feature:
|
// Tests for the cfi-vcall feature:
|
||||||
// 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 -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 -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 -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 -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 -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 -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 -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
|
||||||
|
|
||||||
// Tests for the whole-program-vtables feature:
|
// Tests for the whole-program-vtables feature:
|
||||||
// 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 -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 -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 -flto -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: @[[VTA:[0-9]*]] {{.*}} comdat($"\01??_7A@@6B@")
|
||||||
// MS: @[[VTB:[0-9]*]] {{.*}} comdat($"\01??_7B@@6B0@@")
|
// 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: @[[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]] }
|
// 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 void @_Z2afP1A
|
// ITANIUM: define hidden void @_Z2afP1A
|
||||||
// MS: define void @"\01?af@@YAXPEAUA@@@Z"
|
// MS: define void @"\01?af@@YAXPEAUA@@@Z"
|
||||||
void af(A *a) {
|
void af(A *a) {
|
||||||
// ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A")
|
// ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A")
|
||||||
|
@ -155,7 +155,7 @@ struct D : C {
|
||||||
void m_fn1();
|
void m_fn1();
|
||||||
};
|
};
|
||||||
|
|
||||||
// ITANIUM: define void @_ZN5test21fEPNS_1DE
|
// ITANIUM: define hidden void @_ZN5test21fEPNS_1DE
|
||||||
// MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z"
|
// MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z"
|
||||||
void f(D *d) {
|
void f(D *d) {
|
||||||
// ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE")
|
// ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE")
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 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();
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
// 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 -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 -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 -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
|
// 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
|
||||||
|
|
||||||
// In this test the main thing we are searching for is something like
|
// 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
|
// 'metadata !"1B"' where "1B" is the mangled name of the class we are
|
||||||
|
@ -17,7 +17,7 @@ struct B : A {
|
||||||
|
|
||||||
struct C : A {};
|
struct C : A {};
|
||||||
|
|
||||||
// CHECK-DCAST-LABEL: define void @_Z3abpP1A
|
// CHECK-DCAST-LABEL: define hidden void @_Z3abpP1A
|
||||||
void abp(A *a) {
|
void abp(A *a) {
|
||||||
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
||||||
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
||||||
|
@ -31,7 +31,7 @@ void abp(A *a) {
|
||||||
(void)static_cast<B*>(a);
|
(void)static_cast<B*>(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-DCAST-LABEL: define void @_Z3abrR1A
|
// CHECK-DCAST-LABEL: define hidden void @_Z3abrR1A
|
||||||
void abr(A &a) {
|
void abr(A &a) {
|
||||||
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
||||||
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
||||||
|
@ -45,7 +45,7 @@ void abr(A &a) {
|
||||||
(void)static_cast<B&>(a);
|
(void)static_cast<B&>(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-DCAST-LABEL: define void @_Z4abrrO1A
|
// CHECK-DCAST-LABEL: define hidden void @_Z4abrrO1A
|
||||||
void abrr(A &&a) {
|
void abrr(A &&a) {
|
||||||
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
||||||
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
||||||
|
@ -59,7 +59,7 @@ void abrr(A &&a) {
|
||||||
(void)static_cast<B&&>(a);
|
(void)static_cast<B&&>(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-UCAST-LABEL: define void @_Z3vbpPv
|
// CHECK-UCAST-LABEL: define hidden void @_Z3vbpPv
|
||||||
void vbp(void *p) {
|
void vbp(void *p) {
|
||||||
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
||||||
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
||||||
|
@ -73,7 +73,7 @@ void vbp(void *p) {
|
||||||
(void)static_cast<B*>(p);
|
(void)static_cast<B*>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-UCAST-LABEL: define void @_Z3vbrRc
|
// CHECK-UCAST-LABEL: define hidden void @_Z3vbrRc
|
||||||
void vbr(char &r) {
|
void vbr(char &r) {
|
||||||
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
||||||
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
||||||
|
@ -87,7 +87,7 @@ void vbr(char &r) {
|
||||||
(void)reinterpret_cast<B&>(r);
|
(void)reinterpret_cast<B&>(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-UCAST-LABEL: define void @_Z4vbrrOc
|
// CHECK-UCAST-LABEL: define hidden void @_Z4vbrrOc
|
||||||
void vbrr(char &&r) {
|
void vbrr(char &&r) {
|
||||||
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
|
||||||
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
|
||||||
|
@ -101,32 +101,32 @@ void vbrr(char &&r) {
|
||||||
(void)reinterpret_cast<B&&>(r);
|
(void)reinterpret_cast<B&&>(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-UCAST-LABEL: define void @_Z3vcpPv
|
// CHECK-UCAST-LABEL: define hidden void @_Z3vcpPv
|
||||||
// CHECK-UCAST-STRICT-LABEL: define void @_Z3vcpPv
|
// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3vcpPv
|
||||||
void vcp(void *p) {
|
void vcp(void *p) {
|
||||||
// CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
|
// CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
|
||||||
// CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
|
// CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
|
||||||
(void)static_cast<C*>(p);
|
(void)static_cast<C*>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-UCAST-LABEL: define void @_Z3bcpP1B
|
// CHECK-UCAST-LABEL: define hidden void @_Z3bcpP1B
|
||||||
// CHECK-UCAST-STRICT-LABEL: define void @_Z3bcpP1B
|
// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3bcpP1B
|
||||||
void bcp(B *p) {
|
void bcp(B *p) {
|
||||||
// CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
|
// CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
|
||||||
// CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
|
// CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
|
||||||
(void)(C *)p;
|
(void)(C *)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-UCAST-LABEL: define void @_Z8bcp_callP1B
|
// CHECK-UCAST-LABEL: define hidden void @_Z8bcp_callP1B
|
||||||
// CHECK-UCAST-STRICT-LABEL: define void @_Z8bcp_callP1B
|
// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z8bcp_callP1B
|
||||||
void bcp_call(B *p) {
|
void bcp_call(B *p) {
|
||||||
// CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
|
// CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
|
||||||
// CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
|
// CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
|
||||||
((C *)p)->f();
|
((C *)p)->f();
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-UCAST-LABEL: define i32 @_Z6a_callP1A
|
// CHECK-UCAST-LABEL: define hidden i32 @_Z6a_callP1A
|
||||||
// CHECK-UCAST-STRICT-LABEL: define i32 @_Z6a_callP1A
|
// CHECK-UCAST-STRICT-LABEL: define hidden i32 @_Z6a_callP1A
|
||||||
int a_call(A *a) {
|
int a_call(A *a) {
|
||||||
// CHECK-UCAST-NOT: @llvm.bitset.test
|
// CHECK-UCAST-NOT: @llvm.bitset.test
|
||||||
// CHECK-UCAST-STRICT-NOT: @llvm.bitset.test
|
// CHECK-UCAST-STRICT-NOT: @llvm.bitset.test
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// 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 -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 -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 -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
|
||||||
|
|
||||||
struct A {
|
struct A {
|
||||||
A();
|
A();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// RUN: %clang_cc1 -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 | 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
|
// 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
|
||||||
|
|
||||||
struct A {
|
struct A {
|
||||||
A();
|
A();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// 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 -fvisibility hidden -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
|
// 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
|
||||||
|
|
||||||
struct A {
|
struct A {
|
||||||
virtual void f();
|
virtual void f();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 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
|
// 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
|
||||||
|
|
||||||
// CHECK: [[STATS:@[^ ]*]] = internal global { i8*, i32, [5 x [2 x i8*]] } { i8* null, i32 5, [5 x [2 x i8*]]
|
// 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,
|
// CHECK: {{\[\[}}2 x i8*] zeroinitializer,
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// CHECK-MT-NOT: "-D_DEBUG"
|
// CHECK-MT-NOT: "-D_DEBUG"
|
||||||
// CHECK-MT: "-D_MT"
|
// CHECK-MT: "-D_MT"
|
||||||
// CHECK-MT-NOT: "-D_DLL"
|
// CHECK-MT-NOT: "-D_DLL"
|
||||||
|
// CHECK-MT: "-flto-visibility-public-std"
|
||||||
// CHECK-MT: "--dependent-lib=libcmt"
|
// CHECK-MT: "--dependent-lib=libcmt"
|
||||||
// CHECK-MT: "--dependent-lib=oldnames"
|
// CHECK-MT: "--dependent-lib=oldnames"
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
// CHECK-MTd: "-D_DEBUG"
|
// CHECK-MTd: "-D_DEBUG"
|
||||||
// CHECK-MTd: "-D_MT"
|
// CHECK-MTd: "-D_MT"
|
||||||
// CHECK-MTd-NOT: "-D_DLL"
|
// CHECK-MTd-NOT: "-D_DLL"
|
||||||
|
// CHECK-MTd: "-flto-visibility-public-std"
|
||||||
// CHECK-MTd: "--dependent-lib=libcmtd"
|
// CHECK-MTd: "--dependent-lib=libcmtd"
|
||||||
// CHECK-MTd: "--dependent-lib=oldnames"
|
// CHECK-MTd: "--dependent-lib=oldnames"
|
||||||
|
|
||||||
|
|
|
@ -291,21 +291,29 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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-linux-gnu -fvisibility=hidden -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-apple-darwin10 -fvisibility=hidden -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 -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 -fsanitize=cfi-unrelated-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-UCAST
|
// 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 -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-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
|
// RUN: %clang -target x86_64-linux-gnu -flto -fvisibility=hidden -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: -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-DCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast
|
||||||
// CHECK-CFI-UCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-unrelated-cast
|
// CHECK-CFI-UCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-unrelated-cast
|
||||||
// CHECK-CFI-NVCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-nvcall
|
// CHECK-CFI-NVCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-nvcall
|
||||||
// CHECK-CFI-VCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-vcall
|
// CHECK-CFI-VCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-vcall
|
||||||
|
|
||||||
// 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
|
// 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
|
||||||
// CHECK-CFI-NOLTO: '-fsanitize=cfi-derived-cast' only allowed with '-flto'
|
// 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
|
// 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'
|
// CHECK-CFI-ICALL-MIPS: unsupported option '-fsanitize=cfi-icall' for target 'mips-unknown-linux'
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,2 @@
|
||||||
// RUN: %clang -target x86_64-unknown-linux -fwhole-program-vtables -### %s 2>&1 | FileCheck --check-prefix=NO-LTO %s
|
// 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'
|
// 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"
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
// RUN: %clang -MD -MF - %s -fsyntax-only -I ./ | FileCheck -check-prefix=CHECK-SIX %s
|
// RUN: %clang -MD -MF - %s -fsyntax-only -I ./ | FileCheck -check-prefix=CHECK-SIX %s
|
||||||
// CHECK-SIX: {{ }}x.h
|
// CHECK-SIX: {{ }}x.h
|
||||||
// RUN: echo "fun:foo" > %t.blacklist
|
// RUN: echo "fun:foo" > %t.blacklist
|
||||||
// RUN: %clang -MD -MF - %s -fsyntax-only -fsanitize=cfi-vcall -flto -fsanitize-blacklist=%t.blacklist -I ./ | FileCheck -check-prefix=CHECK-SEVEN %s
|
// RUN: %clang -MD -MF - %s -fsyntax-only -fsanitize=cfi-vcall -flto -fvisibility=hidden -fsanitize-blacklist=%t.blacklist -I ./ | FileCheck -check-prefix=CHECK-SEVEN %s
|
||||||
// CHECK-SEVEN: .blacklist
|
// CHECK-SEVEN: .blacklist
|
||||||
// CHECK-SEVEN: {{ }}x.h
|
// CHECK-SEVEN: {{ }}x.h
|
||||||
#ifndef INCLUDE_FLAG_TEST
|
#ifndef INCLUDE_FLAG_TEST
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
// 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}}
|
||||||
|
};
|
Loading…
Reference in New Issue