forked from OSchip/llvm-project
Fix undefined behavior: member function calls where 'this' is a null pointer.
llvm-svn: 162430
This commit is contained in:
parent
7bdc8ae20b
commit
802c4b7015
|
@ -33,11 +33,11 @@ namespace clang {
|
||||||
char Data[1]; // Variable sized.
|
char Data[1]; // Variable sized.
|
||||||
|
|
||||||
void addRef() {
|
void addRef() {
|
||||||
if (this) ++RefCount;
|
++RefCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dropRef() {
|
void dropRef() {
|
||||||
if (this && --RefCount == 0)
|
if (--RefCount == 0)
|
||||||
delete [] (char*)this;
|
delete [] (char*)this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -63,22 +63,27 @@ namespace clang {
|
||||||
|
|
||||||
RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End)
|
RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End)
|
||||||
: StrData(Str), StartOffs(Start), EndOffs(End) {
|
: StrData(Str), StartOffs(Start), EndOffs(End) {
|
||||||
StrData->addRef();
|
if (StrData)
|
||||||
|
StrData->addRef();
|
||||||
}
|
}
|
||||||
RopePiece(const RopePiece &RP)
|
RopePiece(const RopePiece &RP)
|
||||||
: StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) {
|
: StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) {
|
||||||
StrData->addRef();
|
if (StrData)
|
||||||
|
StrData->addRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
~RopePiece() {
|
~RopePiece() {
|
||||||
StrData->dropRef();
|
if (StrData)
|
||||||
|
StrData->dropRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator=(const RopePiece &RHS) {
|
void operator=(const RopePiece &RHS) {
|
||||||
if (StrData != RHS.StrData) {
|
if (StrData != RHS.StrData) {
|
||||||
StrData->dropRef();
|
if (StrData)
|
||||||
|
StrData->dropRef();
|
||||||
StrData = RHS.StrData;
|
StrData = RHS.StrData;
|
||||||
StrData->addRef();
|
if (StrData)
|
||||||
|
StrData->addRef();
|
||||||
}
|
}
|
||||||
StartOffs = RHS.StartOffs;
|
StartOffs = RHS.StartOffs;
|
||||||
EndOffs = RHS.EndOffs;
|
EndOffs = RHS.EndOffs;
|
||||||
|
@ -191,7 +196,8 @@ public:
|
||||||
|
|
||||||
~RewriteRope() {
|
~RewriteRope() {
|
||||||
// If we had an allocation buffer, drop our reference to it.
|
// If we had an allocation buffer, drop our reference to it.
|
||||||
AllocBuffer->dropRef();
|
if (AllocBuffer)
|
||||||
|
AllocBuffer->dropRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef RopePieceBTree::iterator iterator;
|
typedef RopePieceBTree::iterator iterator;
|
||||||
|
|
|
@ -59,7 +59,7 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
|
||||||
return false; // id/NSObject is not safe for weak.
|
return false; // id/NSObject is not safe for weak.
|
||||||
if (!AllowOnUnknownClass && !Class->hasDefinition())
|
if (!AllowOnUnknownClass && !Class->hasDefinition())
|
||||||
return false; // forward classes are not verifiable, therefore not safe.
|
return false; // forward classes are not verifiable, therefore not safe.
|
||||||
if (Class->isArcWeakrefUnavailable())
|
if (Class && Class->isArcWeakrefUnavailable())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10438,10 +10438,10 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
|
||||||
// If this definition appears within the record, do the checking when
|
// If this definition appears within the record, do the checking when
|
||||||
// the record is complete.
|
// the record is complete.
|
||||||
const FunctionDecl *Primary = MD;
|
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'
|
// Find the uninstantiated declaration that actually had the '= default'
|
||||||
// on it.
|
// on it.
|
||||||
MD->getTemplateInstantiationPattern()->isDefined(Primary);
|
Pattern->isDefined(Primary);
|
||||||
|
|
||||||
if (Primary == Primary->getCanonicalDecl())
|
if (Primary == Primary->getCanonicalDecl())
|
||||||
return;
|
return;
|
||||||
|
@ -10966,14 +10966,16 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
|
||||||
if (Ctor->isInvalidDecl())
|
if (Ctor->isInvalidDecl())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const FunctionDecl *FNTarget = 0;
|
CXXConstructorDecl *Target = Ctor->getTargetConstructor();
|
||||||
CXXConstructorDecl *Target;
|
|
||||||
|
// Target may not be determinable yet, for instance if this is a dependent
|
||||||
// We ignore the result here since if we don't have a body, Target will be
|
// call in an uninstantiated template.
|
||||||
// null below.
|
if (Target) {
|
||||||
(void)Ctor->getTargetConstructor()->hasBody(FNTarget);
|
const FunctionDecl *FNTarget = 0;
|
||||||
Target
|
(void)Target->hasBody(FNTarget);
|
||||||
= const_cast<CXXConstructorDecl*>(cast_or_null<CXXConstructorDecl>(FNTarget));
|
Target = const_cast<CXXConstructorDecl*>(
|
||||||
|
cast_or_null<CXXConstructorDecl>(FNTarget));
|
||||||
|
}
|
||||||
|
|
||||||
CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
|
CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
|
||||||
// Avoid dereferencing a null pointer here.
|
// Avoid dereferencing a null pointer here.
|
||||||
|
@ -10997,17 +10999,18 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
|
||||||
diag::warn_delegating_ctor_cycle)
|
diag::warn_delegating_ctor_cycle)
|
||||||
<< Ctor;
|
<< 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)
|
if (TCanonical != Canonical)
|
||||||
S.Diag(Target->getLocation(), diag::note_it_delegates_to);
|
S.Diag(Target->getLocation(), diag::note_it_delegates_to);
|
||||||
|
|
||||||
CXXConstructorDecl *C = Target;
|
CXXConstructorDecl *C = Target;
|
||||||
while (C->getCanonicalDecl() != Canonical) {
|
while (C->getCanonicalDecl() != Canonical) {
|
||||||
|
const FunctionDecl *FNTarget = 0;
|
||||||
(void)C->getTargetConstructor()->hasBody(FNTarget);
|
(void)C->getTargetConstructor()->hasBody(FNTarget);
|
||||||
assert(FNTarget && "Ctor cycle through bodiless function");
|
assert(FNTarget && "Ctor cycle through bodiless function");
|
||||||
|
|
||||||
C
|
C = const_cast<CXXConstructorDecl*>(
|
||||||
= const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget));
|
cast<CXXConstructorDecl>(FNTarget));
|
||||||
S.Diag(C->getLocation(), diag::note_which_delegates_to);
|
S.Diag(C->getLocation(), diag::note_which_delegates_to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11030,9 +11033,8 @@ void Sema::CheckDelegatingCtorCycles() {
|
||||||
for (DelegatingCtorDeclsType::iterator
|
for (DelegatingCtorDeclsType::iterator
|
||||||
I = DelegatingCtorDecls.begin(ExternalSource),
|
I = DelegatingCtorDecls.begin(ExternalSource),
|
||||||
E = DelegatingCtorDecls.end();
|
E = DelegatingCtorDecls.end();
|
||||||
I != E; ++I) {
|
I != E; ++I)
|
||||||
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
|
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
|
||||||
}
|
|
||||||
|
|
||||||
for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
|
for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
|
||||||
(*CI)->setInvalidDecl();
|
(*CI)->setInvalidDecl();
|
||||||
|
|
|
@ -3101,8 +3101,8 @@ bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,
|
||||||
canExprType->isObjCObjectPointerType()) {
|
canExprType->isObjCObjectPointerType()) {
|
||||||
if (const ObjCObjectPointerType *ObjT =
|
if (const ObjCObjectPointerType *ObjT =
|
||||||
canExprType->getAs<ObjCObjectPointerType>())
|
canExprType->getAs<ObjCObjectPointerType>())
|
||||||
if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable())
|
if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl())
|
||||||
return false;
|
return !ObjI->isArcWeakrefUnavailable();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -886,12 +886,14 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
||||||
if (lifetime == Qualifiers::OCL_Weak) {
|
if (lifetime == Qualifiers::OCL_Weak) {
|
||||||
bool err = false;
|
bool err = false;
|
||||||
if (const ObjCObjectPointerType *ObjT =
|
if (const ObjCObjectPointerType *ObjT =
|
||||||
PropertyIvarType->getAs<ObjCObjectPointerType>())
|
PropertyIvarType->getAs<ObjCObjectPointerType>()) {
|
||||||
if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) {
|
const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
|
||||||
|
if (ObjI && ObjI->isArcWeakrefUnavailable()) {
|
||||||
Diag(PropertyDiagLoc, diag::err_arc_weak_unavailable_property);
|
Diag(PropertyDiagLoc, diag::err_arc_weak_unavailable_property);
|
||||||
Diag(property->getLocation(), diag::note_property_declare);
|
Diag(property->getLocation(), diag::note_property_declare);
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!err && !getLangOpts().ObjCARCWeak) {
|
if (!err && !getLangOpts().ObjCARCWeak) {
|
||||||
Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
|
Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
|
||||||
Diag(property->getLocation(), diag::note_property_declare);
|
Diag(property->getLocation(), diag::note_property_declare);
|
||||||
|
|
|
@ -1999,9 +1999,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
|
||||||
for (unsigned I = 0; I < Depth; ++I)
|
for (unsigned I = 0; I < Depth; ++I)
|
||||||
TemplateArgLists.addOuterTemplateArguments(0, 0);
|
TemplateArgLists.addOuterTemplateArguments(0, 0);
|
||||||
|
|
||||||
|
LocalInstantiationScope Scope(*this);
|
||||||
InstantiatingTemplate Inst(*this, TemplateLoc, Template);
|
InstantiatingTemplate Inst(*this, TemplateLoc, Template);
|
||||||
if (Inst)
|
if (Inst)
|
||||||
return QualType();
|
return QualType();
|
||||||
|
|
||||||
CanonType = SubstType(Pattern->getUnderlyingType(),
|
CanonType = SubstType(Pattern->getUnderlyingType(),
|
||||||
TemplateArgLists, AliasTemplate->getLocation(),
|
TemplateArgLists, AliasTemplate->getLocation(),
|
||||||
AliasTemplate->getDeclName());
|
AliasTemplate->getDeclName());
|
||||||
|
|
|
@ -570,6 +570,9 @@ static void PrepareArgumentPackDeduction(Sema &S,
|
||||||
SavedPacks[I] = Deduced[PackIndices[I]];
|
SavedPacks[I] = Deduced[PackIndices[I]];
|
||||||
Deduced[PackIndices[I]] = TemplateArgument();
|
Deduced[PackIndices[I]] = TemplateArgument();
|
||||||
|
|
||||||
|
if (!S.CurrentInstantiationScope)
|
||||||
|
continue;
|
||||||
|
|
||||||
// If the template arugment pack was explicitly specified, add that to
|
// If the template arugment pack was explicitly specified, add that to
|
||||||
// the set of deduced arguments.
|
// the set of deduced arguments.
|
||||||
const TemplateArgument *ExplicitArgs;
|
const TemplateArgument *ExplicitArgs;
|
||||||
|
@ -2601,7 +2604,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
||||||
// explicitly-specified set (C++0x [temp.arg.explicit]p9).
|
// explicitly-specified set (C++0x [temp.arg.explicit]p9).
|
||||||
const TemplateArgument *ExplicitArgs;
|
const TemplateArgument *ExplicitArgs;
|
||||||
unsigned NumExplicitArgs;
|
unsigned NumExplicitArgs;
|
||||||
if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
|
if (CurrentInstantiationScope &&
|
||||||
|
CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
|
||||||
&NumExplicitArgs)
|
&NumExplicitArgs)
|
||||||
== Param)
|
== Param)
|
||||||
Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
|
Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
|
||||||
|
|
|
@ -520,7 +520,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
|
||||||
const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
|
const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
|
||||||
|
|
||||||
if (VarContext == CurrentContext) {
|
if (VarContext == CurrentContext) {
|
||||||
// If no statemetnt is provided, everything is live.
|
// If no statement is provided, everything is live.
|
||||||
if (!Loc)
|
if (!Loc)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -548,7 +548,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return VarContext->isParentOf(CurrentContext);
|
return !VarContext || VarContext->isParentOf(CurrentContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolVisitor::~SymbolVisitor() {}
|
SymbolVisitor::~SymbolVisitor() {}
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace clang {
|
||||||
class RewriterTestContext {
|
class RewriterTestContext {
|
||||||
public:
|
public:
|
||||||
RewriterTestContext()
|
RewriterTestContext()
|
||||||
: Diagnostics(llvm::IntrusiveRefCntPtr<DiagnosticIDs>()),
|
: Diagnostics(llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs)),
|
||||||
DiagnosticPrinter(llvm::outs(), DiagnosticOptions()),
|
DiagnosticPrinter(llvm::outs(), DiagnosticOptions()),
|
||||||
Files((FileSystemOptions())),
|
Files((FileSystemOptions())),
|
||||||
Sources(Diagnostics, Files),
|
Sources(Diagnostics, Files),
|
||||||
|
|
Loading…
Reference in New Issue