From 52c326ec78bb708cff384600aa695911e6aa8562 Mon Sep 17 00:00:00 2001 From: Edwin Vane Date: Fri, 15 Mar 2013 18:10:07 +0000 Subject: [PATCH] Prevent nullptr_t-typed exprs from being replaced The Use-Nullptr transform was replacing nullptr_t-typed expressions because in the AST such expressions have an implicit NullToPointer cast around them. Now the transform ignores these expressions. Fixes PR15414. llvm-svn: 177168 --- .../cpp11-migrate/UseNullptr/NullptrMatchers.cpp | 33 ++++++++++++++++++---- .../test/cpp11-migrate/UseNullptr/nullptr_t.cpp | 26 ++++++++++++----- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.cpp index a6522a1..86e00c1 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.cpp +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.cpp @@ -37,17 +37,40 @@ AST_MATCHER(CastExpr, isNullToPointer) { Node.getCastKind() == CK_NullToMemberPointer; } +AST_MATCHER(Type, sugaredNullptrType) { + const Type *DesugaredType = Node.getUnqualifiedDesugaredType(); + if (const BuiltinType *BT = dyn_cast(DesugaredType)) + return BT->getKind() == BuiltinType::NullPtr; + return false; +} + } // end namespace ast_matchers } // end namespace clang StatementMatcher makeImplicitCastMatcher() { - return implicitCastExpr(allOf(unless(hasAncestor(explicitCastExpr())), - isNullToPointer())).bind(ImplicitCastNode); + return implicitCastExpr( + isNullToPointer(), + unless(hasAncestor(explicitCastExpr())), + unless( + hasSourceExpression( + hasType(sugaredNullptrType()) + ) + ) + ).bind(ImplicitCastNode); } StatementMatcher makeCastSequenceMatcher() { return explicitCastExpr( - allOf(unless(hasAncestor(explicitCastExpr())), - hasDescendant(implicitCastExpr(isNullToPointer()))) - ).bind(CastSequence); + unless(hasAncestor(explicitCastExpr())), + hasDescendant( + implicitCastExpr( + isNullToPointer(), + unless( + hasSourceExpression( + hasType(sugaredNullptrType()) + ) + ) + ) + ) + ).bind(CastSequence); } diff --git a/clang-tools-extra/test/cpp11-migrate/UseNullptr/nullptr_t.cpp b/clang-tools-extra/test/cpp11-migrate/UseNullptr/nullptr_t.cpp index 84ca100..a973fb3 100644 --- a/clang-tools-extra/test/cpp11-migrate/UseNullptr/nullptr_t.cpp +++ b/clang-tools-extra/test/cpp11-migrate/UseNullptr/nullptr_t.cpp @@ -1,17 +1,29 @@ // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp // RUN: cpp11-migrate -final-syntax-check -use-nullptr %t.cpp -- --std=c++11 -I %S // RUN: FileCheck -input-file=%t.cpp %s -// XFAIL: * -namespace std { typedef decltype(nullptr) nullptr_t; } +namespace std { + +typedef decltype(nullptr) nullptr_t; + +} // namespace std // Just to make sure make_null() could have side effects. void external(); -std::nullptr_t make_null() { external(); return nullptr; } +std::nullptr_t make_null() { + external(); + return nullptr; +} + +void func() { + void *CallTest = make_null(); + // CHECK: void *CallTest = make_null(); + + int var = 1; + void *CommaTest = (var+=2, make_null()); + // CHECK: void *CommaTest = (var+=2, make_null()); -void *call_make_null() -{ - return make_null(); - // CHECK: return make_null(); + int *CastTest = static_cast(make_null()); + // CHECK: int *CastTest = static_cast(make_null()); } -- 2.7.4