diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-04 22:27:30 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-04 22:27:30 +0000 |
commit | 36d02af300a207242f0486b4255420d8be796b21 (patch) | |
tree | adb96320cd351324f25e5d0f3de39541f840d7cc /lib/Sema/SemaInit.cpp | |
parent | d5edd849b6003b97e0e1ee5cf964c10affbe6bce (diff) |
Add a warning for when an array-to-pointer decay is performed on an array
temporary or an array subobject of a class temporary, and the resulting value
is used to initialize a pointer which outlives the temporary. Such a pointer
is always left dangling after the initialization completes and the array's
lifetime ends.
In order to detect this situation, this change also adds an
LValueClassification of LV_ArrayTemporary for temporaries of array type which
aren't subobjects of class temporaries. These occur in C++11 T{...} and GNU C++
(T){...} expressions, when T is an array type. Previously we treated the former
as a generic prvalue and the latter as a class temporary.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157955 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 66cc1e14e5..66a64a9e5c 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4747,6 +4747,43 @@ PerformConstructorInitialization(Sema &S, return move(CurInit); } +/// Determine whether the specified InitializedEntity definitely has a lifetime +/// longer than the current full-expression. Conservatively returns false if +/// it's unclear. +static bool +InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) { + const InitializedEntity *Top = &Entity; + while (Top->getParent()) + Top = Top->getParent(); + + switch (Top->getKind()) { + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_Result: + case InitializedEntity::EK_Exception: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + return true; + + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_ComplexElement: + // Could not determine what the full initialization is. Assume it might not + // outlive the full-expression. + return false; + + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_LambdaCapture: + // The entity being initialized might not outlive the full-expression. + return false; + } + + llvm_unreachable("unknown entity kind"); +} + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -4826,6 +4863,18 @@ InitializationSequence::Perform(Sema &S, << Init->getSourceRange(); } + // Diagnose cases where we initialize a pointer to an array temporary, and the + // pointer obviously outlives the temporary. + if (Args.size() == 1 && Args.get()[0]->getType()->isArrayType() && + Entity.getType()->isPointerType() && + InitializedEntityOutlivesFullExpression(Entity)) { + Expr *Init = Args.get()[0]; + Expr::LValueClassification Kind = Init->ClassifyLValue(S.Context); + if (Kind == Expr::LV_ClassTemporary || Kind == Expr::LV_ArrayTemporary) + S.Diag(Init->getLocStart(), diag::warn_temporary_array_to_pointer_decay) + << Init->getSourceRange(); + } + QualType DestType = Entity.getType().getNonReferenceType(); // FIXME: Ugly hack around the fact that Entity.getType() is not // the same as Entity.getDecl()->getType() in cases involving type merging, |