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.
|
||||
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue