diff --git a/lib/Interpreter/NullDerefProtectionTransformer.cpp b/lib/Interpreter/NullDerefProtectionTransformer.cpp index e95118bf..a814605d 100644 --- a/lib/Interpreter/NullDerefProtectionTransformer.cpp +++ b/lib/Interpreter/NullDerefProtectionTransformer.cpp @@ -57,19 +57,20 @@ extern "C" { using namespace clang; namespace cling { - typedef std::map > nonnull_map_t; + typedef std::map > nonnull_map_t; // NonNullDeclFinder finds the function decls with nonnull attribute args. class NonNullDeclFinder : public RecursiveASTVisitor { private: Sema* m_Sema; - llvm::SmallVector m_NonNullDeclNames; + llvm::OwningPtr m_MangleCtx; + llvm::SmallVector m_NonNullDeclNames; nonnull_map_t m_NonNullArgIndexs; public: NonNullDeclFinder(Sema* S) : m_Sema(S) {} - const llvm::SmallVector& getDeclNames() const { + const llvm::SmallVector& getDeclNames() const { return m_NonNullDeclNames; } @@ -77,6 +78,41 @@ namespace cling { return m_NonNullArgIndexs; } + std::string getMangledName(FunctionDecl* FD) { + // Copied from Interpreter.cpp; + if (!m_MangleCtx) + m_MangleCtx.reset(FD->getASTContext().createMangleContext()); + + std::string mangledName; + if (m_MangleCtx->shouldMangleDeclName(FD)) { + llvm::raw_string_ostream RawStr(mangledName); + switch(FD->getKind()) { + case Decl::CXXConstructor: + //Ctor_Complete, // Complete object ctor + //Ctor_Base, // Base object ctor + //Ctor_CompleteAllocating // Complete object allocating ctor (unused) + m_MangleCtx->mangleCXXCtor(cast(FD), + Ctor_Complete, RawStr); + break; + + case Decl::CXXDestructor: + //Dtor_Deleting, // Deleting dtor + //Dtor_Complete, // Complete object dtor + //Dtor_Base // Base object dtor + m_MangleCtx->mangleCXXDtor(cast(FD), + Dtor_Complete, RawStr); + break; + + default : + m_MangleCtx->mangleName(FD, RawStr); + break; + } + RawStr.flush(); + } else { + mangledName = FD->getNameAsString(); + } + return mangledName; + } // Deal with all the call expr in the transaction. bool VisitCallExpr(CallExpr* TheCall) { if (FunctionDecl* FDecl = TheCall->getDirectCallee()) { @@ -108,7 +144,7 @@ namespace cling { if (ArgIndexs.any()) { // Get the function decl's name. - llvm::StringRef FName = FDecl->getName(); + std::string FName = getMangledName(FDecl); // Store the function decl's name into the vector. m_NonNullDeclNames.push_back(FName); @@ -133,39 +169,8 @@ namespace cling { if (!FD) return; - // Copied from Interpreter.cpp; - if (!m_MangleCtx) - m_MangleCtx.reset(FD->getASTContext().createMangleContext()); - - std::string mangledName; - if (m_MangleCtx->shouldMangleDeclName(FD)) { - llvm::raw_string_ostream RawStr(mangledName); - switch(FD->getKind()) { - case Decl::CXXConstructor: - //Ctor_Complete, // Complete object ctor - //Ctor_Base, // Base object ctor - //Ctor_CompleteAllocating // Complete object allocating ctor (unused) - m_MangleCtx->mangleCXXCtor(cast(FD), - Ctor_Complete, RawStr); - break; - - case Decl::CXXDestructor: - //Dtor_Deleting, // Deleting dtor - //Dtor_Complete, // Complete object dtor - //Dtor_Base // Base object dtor - m_MangleCtx->mangleCXXDtor(cast(FD), - Dtor_Complete, RawStr); - break; - - default : - m_MangleCtx->mangleName(FD, RawStr); - break; - } - RawStr.flush(); - } else { - mangledName = FD->getNameAsString(); - } - + NonNullDeclFinder Finder(m_Sema); + std::string mangledName = Finder.getMangledName(FD); // Find the function in the module. llvm::Function* F = getTransaction()->getModule()->getFunction(mangledName); if (!F) return; @@ -174,8 +179,6 @@ namespace cling { Builder = &TheBuilder; runOnFunction(*F); - NonNullDeclFinder Finder(m_Sema); - // Find all the function decls with null attribute arguments. for (size_t Idx = 0, E = getTransaction()->size(); Idx < E; ++Idx) { Transaction::DelayCallInfo I = (*getTransaction())[Idx]; @@ -185,13 +188,13 @@ namespace cling { Finder.TraverseStmt((*J)->getBody()); } - const llvm::SmallVector& + const llvm::SmallVector& FDeclNames = Finder.getDeclNames(); if (FDeclNames.empty()) return; llvm::Module* M = F->getParent(); - for (llvm::SmallVector::const_iterator + for (llvm::SmallVector::const_iterator i = FDeclNames.begin(), e = FDeclNames.end(); i != e; ++i) { const nonnull_map_t& ArgIndexs = Finder.getArgIndexs(); nonnull_map_t::const_iterator it = ArgIndexs.find(*i); @@ -363,7 +366,7 @@ namespace cling { } void NullDerefProtectionTransformer::handleNonNullArgCall(llvm::Module& M, - const llvm::StringRef& name, const std::bitset<32>& ArgIndexs) { + const std::string& name, const std::bitset<32>& ArgIndexs) { // Get the function by the name. llvm::Function* func = M.getFunction(name); diff --git a/lib/Interpreter/NullDerefProtectionTransformer.h b/lib/Interpreter/NullDerefProtectionTransformer.h index 1d9e54f9..d67a2241 100644 --- a/lib/Interpreter/NullDerefProtectionTransformer.h +++ b/lib/Interpreter/NullDerefProtectionTransformer.h @@ -41,7 +41,7 @@ namespace cling { void instrumentCallInst(llvm::Instruction* TheCall, const std::bitset<32>& ArgIndexs); void handleNonNullArgCall(llvm::Module& M, - const llvm::StringRef& FName, + const std::string& FName, const std::bitset<32>& ArgIndexs); public: diff --git a/test/NullDeref/NonNullArgCustom.C b/test/NullDeref/NonNullArgCustom.C index ea1ade3f..63218eed 100644 --- a/test/NullDeref/NonNullArgCustom.C +++ b/test/NullDeref/NonNullArgCustom.C @@ -1,11 +1,12 @@ -// RUN: cat %s | %cling -Xclang -verify | FileCheck %s -// XFAIL:* +// RUN: cat %s | %cling -Xclang -verify + // We must be able to handle cases where, there is a custom function that has // attributes non-null arguments and we should be able to add a non-null arg // attribute to a say library function. // Qualified functions. +#include namespace custom_namespace { void standaloneFunc(void* p, int q, float* s) __attribute__((nonnull(1,3))) { // expected-warning {{GCC does not allow nonnull attribute in this position on a function definition}} if (!p || !s) @@ -27,9 +28,9 @@ int* p = new int(1); float* f = new float(0.0); const char* charNull = 0; -custom_namespace::standaloneFunc(pNull, 1, fNull); -custom_namespace::standaloneFunc(pNull, 1, f); -custom_namespace::standaloneFunc(p, 1, fNull); +custom_namespace::standaloneFunc(pNull, 1, fNull); // expected-warning {{you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]}} +custom_namespace::standaloneFunc(pNull, 1, f); // expected-warning {{you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]}} +custom_namespace::standaloneFunc(p, 1, fNull); // expected-warning {{you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]}} printf(charNull, ""); // expected-warning {{you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]}} .rawInput 1 @@ -41,7 +42,7 @@ int trampoline() { } .rawInput 0 //CHECK-NOT: Must not be called with 0 args. -trampoline() +//trampoline() //CHECK: (int) 1 .q