Fix ODR violations: a virtual function must be defined, even if it's never

called. Provide an (asserting) definition of Operator's private destructor.
Remove destructors from all classes derived from Operator. We don't need them
for safety, because their implicit definitions would be ill-formed (they'd call
Operator's private destructor), and we don't need them to avoid emitting
vtables, because we don't do anything with Operator subclasses which would
trigger vtable instantiation.

The Operator hierarchy is still a complete disaster with regard to undefined
behavior, but this at least allows LLVM to link when using Clang's
-fcatch-undefined-behavior with a new vptr-based type checking mechanism.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166530 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Smith 2012-10-24 00:30:41 +00:00
parent a6cf7a62a7
commit 30f57da439
2 changed files with 13 additions and 20 deletions

View File

@ -36,8 +36,10 @@ private:
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
void *operator new(size_t s) LLVM_DELETED_FUNCTION; void *operator new(size_t s) LLVM_DELETED_FUNCTION;
Operator() LLVM_DELETED_FUNCTION; Operator() LLVM_DELETED_FUNCTION;
// NOTE: cannot use LLVM_DELETED_FUNCTION because it's not legal to delete
// an overridden method that's not deleted in the base class. // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete
// an overridden method that's not deleted in the base class. Cannot leave
// this unimplemented because that leads to an ODR-violation.
~Operator(); ~Operator();
public: public:
@ -79,8 +81,6 @@ public:
}; };
private: private:
~OverflowingBinaryOperator(); // DO NOT IMPLEMENT
friend class BinaryOperator; friend class BinaryOperator;
friend class ConstantExpr; friend class ConstantExpr;
void setHasNoUnsignedWrap(bool B) { void setHasNoUnsignedWrap(bool B) {
@ -132,8 +132,6 @@ public:
}; };
private: private:
~PossiblyExactOperator(); // DO NOT IMPLEMENT
friend class BinaryOperator; friend class BinaryOperator;
friend class ConstantExpr; friend class ConstantExpr;
void setIsExact(bool B) { void setIsExact(bool B) {
@ -168,9 +166,6 @@ public:
/// FPMathOperator - Utility class for floating point operations which can have /// FPMathOperator - Utility class for floating point operations which can have
/// information about relaxed accuracy requirements attached to them. /// information about relaxed accuracy requirements attached to them.
class FPMathOperator : public Operator { class FPMathOperator : public Operator {
private:
~FPMathOperator(); // DO NOT IMPLEMENT
public: public:
/// \brief Get the maximum error permitted by this operation in ULPs. An /// \brief Get the maximum error permitted by this operation in ULPs. An
@ -191,7 +186,6 @@ public:
/// opcodes. /// opcodes.
template<typename SuperClass, unsigned Opc> template<typename SuperClass, unsigned Opc>
class ConcreteOperator : public SuperClass { class ConcreteOperator : public SuperClass {
~ConcreteOperator(); // DO NOT IMPLEMENT
public: public:
static inline bool classof(const Instruction *I) { static inline bool classof(const Instruction *I) {
return I->getOpcode() == Opc; return I->getOpcode() == Opc;
@ -207,45 +201,35 @@ public:
class AddOperator class AddOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> { : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {
~AddOperator(); // DO NOT IMPLEMENT
}; };
class SubOperator class SubOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> { : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {
~SubOperator(); // DO NOT IMPLEMENT
}; };
class MulOperator class MulOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> { : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {
~MulOperator(); // DO NOT IMPLEMENT
}; };
class ShlOperator class ShlOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> { : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {
~ShlOperator(); // DO NOT IMPLEMENT
}; };
class SDivOperator class SDivOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> { : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> {
~SDivOperator(); // DO NOT IMPLEMENT
}; };
class UDivOperator class UDivOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> { : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> {
~UDivOperator(); // DO NOT IMPLEMENT
}; };
class AShrOperator class AShrOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> { : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {
~AShrOperator(); // DO NOT IMPLEMENT
}; };
class LShrOperator class LShrOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> { : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {
~LShrOperator(); // DO NOT IMPLEMENT
}; };
class GEPOperator class GEPOperator
: public ConcreteOperator<Operator, Instruction::GetElementPtr> { : public ConcreteOperator<Operator, Instruction::GetElementPtr> {
~GEPOperator(); // DO NOT IMPLEMENT
enum { enum {
IsInBounds = (1 << 0) IsInBounds = (1 << 0)
}; };

View File

@ -10,6 +10,7 @@
#include "llvm/Constant.h" #include "llvm/Constant.h"
#include "llvm/GlobalValue.h" #include "llvm/GlobalValue.h"
#include "llvm/User.h" #include "llvm/User.h"
#include "llvm/Operator.h"
namespace llvm { namespace llvm {
@ -78,4 +79,12 @@ void User::operator delete(void *Usr) {
::operator delete(Storage); ::operator delete(Storage);
} }
//===----------------------------------------------------------------------===//
// Operator Class
//===----------------------------------------------------------------------===//
Operator::~Operator() {
llvm_unreachable("should never destroy an Operator");
}
} // End llvm namespace } // End llvm namespace