Fix undefined behavior: member function calls where 'this' is a null pointer.

llvm-svn: 162430
This commit is contained in:
Richard Smith 2012-08-23 06:16:52 +00:00
parent 7bdc8ae20b
commit 802c4b7015
9 changed files with 49 additions and 33 deletions

View File

@ -33,11 +33,11 @@ namespace clang {
char Data[1]; // Variable sized.
void addRef() {
if (this) ++RefCount;
++RefCount;
}
void dropRef() {
if (this && --RefCount == 0)
if (--RefCount == 0)
delete [] (char*)this;
}
};
@ -63,22 +63,27 @@ namespace clang {
RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End)
: StrData(Str), StartOffs(Start), EndOffs(End) {
StrData->addRef();
if (StrData)
StrData->addRef();
}
RopePiece(const RopePiece &RP)
: StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) {
StrData->addRef();
if (StrData)
StrData->addRef();
}
~RopePiece() {
StrData->dropRef();
if (StrData)
StrData->dropRef();
}
void operator=(const RopePiece &RHS) {
if (StrData != RHS.StrData) {
StrData->dropRef();
if (StrData)
StrData->dropRef();
StrData = RHS.StrData;
StrData->addRef();
if (StrData)
StrData->addRef();
}
StartOffs = RHS.StartOffs;
EndOffs = RHS.EndOffs;
@ -191,7 +196,8 @@ public:
~RewriteRope() {
// If we had an allocation buffer, drop our reference to it.
AllocBuffer->dropRef();
if (AllocBuffer)
AllocBuffer->dropRef();
}
typedef RopePieceBTree::iterator iterator;

View File

@ -59,7 +59,7 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
return false; // id/NSObject is not safe for weak.
if (!AllowOnUnknownClass && !Class->hasDefinition())
return false; // forward classes are not verifiable, therefore not safe.
if (Class->isArcWeakrefUnavailable())
if (Class && Class->isArcWeakrefUnavailable())
return false;
}

View File

@ -10438,10 +10438,10 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
// If this definition appears within the record, do the checking when
// the record is complete.
const FunctionDecl *Primary = MD;
if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
if (const FunctionDecl *Pattern = MD->getTemplateInstantiationPattern())
// Find the uninstantiated declaration that actually had the '= default'
// on it.
MD->getTemplateInstantiationPattern()->isDefined(Primary);
Pattern->isDefined(Primary);
if (Primary == Primary->getCanonicalDecl())
return;
@ -10966,14 +10966,16 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
if (Ctor->isInvalidDecl())
return;
const FunctionDecl *FNTarget = 0;
CXXConstructorDecl *Target;
// We ignore the result here since if we don't have a body, Target will be
// null below.
(void)Ctor->getTargetConstructor()->hasBody(FNTarget);
Target
= const_cast<CXXConstructorDecl*>(cast_or_null<CXXConstructorDecl>(FNTarget));
CXXConstructorDecl *Target = Ctor->getTargetConstructor();
// Target may not be determinable yet, for instance if this is a dependent
// call in an uninstantiated template.
if (Target) {
const FunctionDecl *FNTarget = 0;
(void)Target->hasBody(FNTarget);
Target = const_cast<CXXConstructorDecl*>(
cast_or_null<CXXConstructorDecl>(FNTarget));
}
CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
// Avoid dereferencing a null pointer here.
@ -10997,17 +10999,18 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
diag::warn_delegating_ctor_cycle)
<< Ctor;
// Don't add a note for a function delegating directo to itself.
// Don't add a note for a function delegating directly to itself.
if (TCanonical != Canonical)
S.Diag(Target->getLocation(), diag::note_it_delegates_to);
CXXConstructorDecl *C = Target;
while (C->getCanonicalDecl() != Canonical) {
const FunctionDecl *FNTarget = 0;
(void)C->getTargetConstructor()->hasBody(FNTarget);
assert(FNTarget && "Ctor cycle through bodiless function");
C
= const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget));
C = const_cast<CXXConstructorDecl*>(
cast<CXXConstructorDecl>(FNTarget));
S.Diag(C->getLocation(), diag::note_which_delegates_to);
}
}
@ -11030,9 +11033,8 @@ void Sema::CheckDelegatingCtorCycles() {
for (DelegatingCtorDeclsType::iterator
I = DelegatingCtorDecls.begin(ExternalSource),
E = DelegatingCtorDecls.end();
I != E; ++I) {
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
}
I != E; ++I)
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
(*CI)->setInvalidDecl();

View File

@ -3101,8 +3101,8 @@ bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,
canExprType->isObjCObjectPointerType()) {
if (const ObjCObjectPointerType *ObjT =
canExprType->getAs<ObjCObjectPointerType>())
if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable())
return false;
if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl())
return !ObjI->isArcWeakrefUnavailable();
}
return true;
}

View File

@ -886,12 +886,14 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (lifetime == Qualifiers::OCL_Weak) {
bool err = false;
if (const ObjCObjectPointerType *ObjT =
PropertyIvarType->getAs<ObjCObjectPointerType>())
if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) {
PropertyIvarType->getAs<ObjCObjectPointerType>()) {
const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
if (ObjI && ObjI->isArcWeakrefUnavailable()) {
Diag(PropertyDiagLoc, diag::err_arc_weak_unavailable_property);
Diag(property->getLocation(), diag::note_property_declare);
err = true;
}
}
if (!err && !getLangOpts().ObjCARCWeak) {
Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
Diag(property->getLocation(), diag::note_property_declare);

View File

@ -1999,9 +1999,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
for (unsigned I = 0; I < Depth; ++I)
TemplateArgLists.addOuterTemplateArguments(0, 0);
LocalInstantiationScope Scope(*this);
InstantiatingTemplate Inst(*this, TemplateLoc, Template);
if (Inst)
return QualType();
CanonType = SubstType(Pattern->getUnderlyingType(),
TemplateArgLists, AliasTemplate->getLocation(),
AliasTemplate->getDeclName());

View File

@ -570,6 +570,9 @@ static void PrepareArgumentPackDeduction(Sema &S,
SavedPacks[I] = Deduced[PackIndices[I]];
Deduced[PackIndices[I]] = TemplateArgument();
if (!S.CurrentInstantiationScope)
continue;
// If the template arugment pack was explicitly specified, add that to
// the set of deduced arguments.
const TemplateArgument *ExplicitArgs;
@ -2601,7 +2604,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// explicitly-specified set (C++0x [temp.arg.explicit]p9).
const TemplateArgument *ExplicitArgs;
unsigned NumExplicitArgs;
if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
if (CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
&NumExplicitArgs)
== Param)
Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));

View File

@ -520,7 +520,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
if (VarContext == CurrentContext) {
// If no statemetnt is provided, everything is live.
// If no statement is provided, everything is live.
if (!Loc)
return true;
@ -548,7 +548,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
return false;
}
return VarContext->isParentOf(CurrentContext);
return !VarContext || VarContext->isParentOf(CurrentContext);
}
SymbolVisitor::~SymbolVisitor() {}

View File

@ -35,7 +35,7 @@ namespace clang {
class RewriterTestContext {
public:
RewriterTestContext()
: Diagnostics(llvm::IntrusiveRefCntPtr<DiagnosticIDs>()),
: Diagnostics(llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs)),
DiagnosticPrinter(llvm::outs(), DiagnosticOptions()),
Files((FileSystemOptions())),
Sources(Diagnostics, Files),