summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaCXXCast.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-05-02 18:21:19 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-05-02 18:21:19 +0000
commit69a2c924b9e825616c62c7985c81410b14657d5c (patch)
tree1c29b896a8418db7dc727b38503b81845349daba /clang/lib/Sema/SemaCXXCast.cpp
parent420ab5f1802bf9451b4cd1986bf1679e97075739 (diff)
downloadbcm5719-llvm-69a2c924b9e825616c62c7985c81410b14657d5c.tar.gz
bcm5719-llvm-69a2c924b9e825616c62c7985c81410b14657d5c.zip
Add a warning for when reinterpret_cast leads to undefined behavior, patch by Richard Trieu!
llvm-svn: 130703
Diffstat (limited to 'clang/lib/Sema/SemaCXXCast.cpp')
-rw-r--r--clang/lib/Sema/SemaCXXCast.cpp60
1 files changed, 60 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp
index ed54f0f5442..2ea3b46829f 100644
--- a/clang/lib/Sema/SemaCXXCast.cpp
+++ b/clang/lib/Sema/SemaCXXCast.cpp
@@ -1288,6 +1288,61 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
return TC_Success;
}
+// Checks for undefined behavior in reinterpret_cast.
+// The cases that is checked for is:
+// *reinterpret_cast<T*>(&a)
+// reinterpret_cast<T&>(a)
+// where accessing 'a' as type 'T' will result in undefined behavior.
+void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
+ bool IsDereference,
+ SourceRange Range) {
+ unsigned DiagID = IsDereference ?
+ diag::warn_pointer_indirection_from_incompatible_type :
+ diag::warn_undefined_reinterpret_cast;
+
+ if (Diags.getDiagnosticLevel(DiagID, Range.getBegin()) ==
+ Diagnostic::Ignored) {
+ return;
+ }
+
+ QualType SrcTy, DestTy;
+ if (IsDereference) {
+ if (!SrcType->getAs<PointerType>() || !DestType->getAs<PointerType>()) {
+ return;
+ }
+ SrcTy = SrcType->getPointeeType();
+ DestTy = DestType->getPointeeType();
+ } else {
+ if (!DestType->getAs<ReferenceType>()) {
+ return;
+ }
+ SrcTy = SrcType;
+ DestTy = DestType->getPointeeType();
+ }
+
+ // Cast is compatible if the types are the same.
+ if (Context.hasSameUnqualifiedType(DestTy, SrcTy)) {
+ return;
+ }
+ // or one of the types is a char or void type
+ if (DestTy->isAnyCharacterType() || DestTy->isVoidType() ||
+ SrcTy->isAnyCharacterType() || SrcTy->isVoidType()) {
+ return;
+ }
+ // or one of the types is a tag type.
+ if (isa<TagType>(SrcTy) || isa<TagType>(DestTy)) {
+ return;
+ }
+
+ if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) ||
+ (SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) {
+ if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) {
+ return;
+ }
+ }
+
+ Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range;
+}
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
@@ -1324,6 +1379,11 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return TC_NotApplicable;
}
+ if (!CStyle) {
+ Self.CheckCompatibleReinterpretCast(SrcType, DestType,
+ /*isDereference=*/false, OpRange);
+ }
+
// C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the
// same effect as the conversion *reinterpret_cast<T*>(&x) with the
// built-in & and * operators.
OpenPOWER on IntegriCloud