r208724 - PR19729: Delete a bunch of bogus code in Sema::FindAllocationOverload. This

Richard Smith richard-llvm at metafoo.co.uk
Tue May 13 12:56:21 PDT 2014


Author: rsmith
Date: Tue May 13 14:56:21 2014
New Revision: 208724

URL: http://llvm.org/viewvc/llvm-project?rev=208724&view=rev
Log:
PR19729: Delete a bunch of bogus code in Sema::FindAllocationOverload. This
caused us to perform copy-initialization for the parameters of an allocation
function called by a new-expression multiple times, resulting in us rejecting
allocations that passed non-copyable parameters (and much worse things in
MSVC compat mode, where we potentially called this function multiple times).

Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
    cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=208724&r1=208723&r2=208724&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue May 13 14:56:21 2014
@@ -4164,18 +4164,14 @@ bool Sema::GatherArgumentsForCall(Source
                                   VariadicCallType CallType, bool AllowExplicit,
                                   bool IsListInitialization) {
   unsigned NumParams = Proto->getNumParams();
-  unsigned NumArgsToCheck = Args.size();
   bool Invalid = false;
-  if (Args.size() != NumParams)
-    // Use default arguments for missing arguments
-    NumArgsToCheck = NumParams;
   unsigned ArgIx = 0;
   // Continue to check argument types (even if we have too few/many args).
-  for (unsigned i = FirstParam; i != NumArgsToCheck; i++) {
+  for (unsigned i = FirstParam; i < NumParams; i++) {
     QualType ProtoArgType = Proto->getParamType(i);
 
     Expr *Arg;
-    ParmVarDecl *Param;
+    ParmVarDecl *Param = FDecl ? FDecl->getParamDecl(i) : nullptr;
     if (ArgIx < Args.size()) {
       Arg = Args[ArgIx++];
 
@@ -4184,11 +4180,6 @@ bool Sema::GatherArgumentsForCall(Source
                               diag::err_call_incomplete_argument, Arg))
         return true;
 
-      // Pass the argument
-      Param = 0;
-      if (FDecl && i < FDecl->getNumParams())
-        Param = FDecl->getParamDecl(i);
-
       // Strip the unbridged-cast placeholder expression off, if applicable.
       bool CFAudited = false;
       if (Arg->getType() == Context.ARCUnbridgedCastTy &&
@@ -4209,7 +4200,7 @@ bool Sema::GatherArgumentsForCall(Source
       // Remember that parameter belongs to a CF audited API.
       if (CFAudited)
         Entity.setParameterCFAudited();
-      
+
       ExprResult ArgE = PerformCopyInitialization(Entity,
                                                   SourceLocation(),
                                                   Owned(Arg),
@@ -4220,8 +4211,7 @@ bool Sema::GatherArgumentsForCall(Source
 
       Arg = ArgE.takeAs<Expr>();
     } else {
-      assert(FDecl && "can't use default arguments without a known callee");
-      Param = FDecl->getParamDecl(i);
+      assert(Param && "can't use default arguments without a known callee");
 
       ExprResult ArgExpr =
         BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=208724&r1=208723&r2=208724&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue May 13 14:56:21 2014
@@ -1414,12 +1414,14 @@ Sema::BuildCXXNew(SourceRange Range, boo
 
   SmallVector<Expr *, 8> AllPlaceArgs;
   if (OperatorNew) {
-    // Add default arguments, if any.
     const FunctionProtoType *Proto =
-      OperatorNew->getType()->getAs<FunctionProtoType>();
-    VariadicCallType CallType =
-      Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
-
+        OperatorNew->getType()->getAs<FunctionProtoType>();
+    VariadicCallType CallType = Proto->isVariadic() ? VariadicFunction
+                                                    : VariadicDoesNotApply;
+
+    // We've already converted the placement args, just fill in any default
+    // arguments. Skip the first parameter because we don't have a corresponding
+    // argument.
     if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto, 1,
                                PlacementArgs, AllPlaceArgs, CallType))
       return ExprError();
@@ -1427,6 +1429,7 @@ Sema::BuildCXXNew(SourceRange Range, boo
     if (!AllPlaceArgs.empty())
       PlacementArgs = AllPlaceArgs;
 
+    // FIXME: This is wrong: PlacementArgs misses out the first (size) argument.
     DiagnoseSentinelCalls(OperatorNew, PlacementLParen, PlacementArgs);
 
     // FIXME: Missing call to CheckFunctionCall or equivalent
@@ -1684,11 +1687,6 @@ bool Sema::FindAllocationFunctions(Sourc
     return false;
   }
 
-  // FindAllocationOverload can change the passed in arguments, so we need to
-  // copy them back.
-  if (!PlaceArgs.empty())
-    std::copy(AllocArgs.begin() + 1, AllocArgs.end(), PlaceArgs.data());
-
   // C++ [expr.new]p19:
   //
   //   If the new-expression begins with a unary :: operator, the
@@ -1832,8 +1830,22 @@ bool Sema::FindAllocationFunctions(Sourc
   return false;
 }
 
-/// FindAllocationOverload - Find an fitting overload for the allocation
-/// function in the specified scope.
+/// \brief Find an fitting overload for the allocation function
+/// in the specified scope.
+///
+/// \param StartLoc The location of the 'new' token.
+/// \param SourceRange The range of the placement arguments.
+/// \param Name The name of the function ('operator new' or 'operator new[]').
+/// \param Args The placement arguments specified.
+/// \param Ctx The scope in which we should search; either a class scope or the
+///        translation unit.
+/// \param AllowMissing If \c true, report an error if we can't find any
+///        allocation functions. Otherwise, succeed but don't fill in \p
+///        Operator.
+/// \param Operator Filled in with the found allocation function. Unchanged if
+///        no allocation function was found.
+/// \param Diagnose If \c true, issue errors if the allocation function is not
+///        usable.
 bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
                                   DeclarationName Name, MultiExprArg Args,
                                   DeclContext *Ctx,
@@ -1879,33 +1891,11 @@ bool Sema::FindAllocationOverload(Source
   case OR_Success: {
     // Got one!
     FunctionDecl *FnDecl = Best->Function;
-    MarkFunctionReferenced(StartLoc, FnDecl);
-    // The first argument is size_t, and the first parameter must be size_t,
-    // too. This is checked on declaration and can be assumed. (It can't be
-    // asserted on, though, since invalid decls are left in there.)
-    // Watch out for variadic allocator function.
-    unsigned NumArgsInFnDecl = FnDecl->getNumParams();
-    for (unsigned i = 0; (i < Args.size() && i < NumArgsInFnDecl); ++i) {
-      InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
-                                                       FnDecl->getParamDecl(i));
-
-      if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i])))
-        return true;
-
-      ExprResult Result
-        = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i]));
-      if (Result.isInvalid())
-        return true;
-
-      Args[i] = Result.takeAs<Expr>();
-    }
-
-    Operator = FnDecl;
-
     if (CheckAllocationAccess(StartLoc, Range, R.getNamingClass(),
                               Best->FoundDecl, Diagnose) == AR_inaccessible)
       return true;
 
+    Operator = FnDecl;
     return false;
   }
 

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp?rev=208724&r1=208723&r2=208724&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Tue May 13 14:56:21 2014
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -fexceptions -verify %s
 
 struct one { char c[1]; };
 struct two { char c[2]; };
@@ -304,7 +304,6 @@ namespace init_list_default {
   B b {}; // calls default constructor
 }
 
-
 // PR13470, <rdar://problem/11974632>
 namespace PR13470 {
   struct W {
@@ -365,3 +364,14 @@ namespace PR13470 {
     yi.h(); // ok, all diagnostics produced in template definition
   }
 }
+
+namespace PR19729 {
+  struct A {
+    A(int);
+    A(const A&) = delete;
+  };
+  struct B {
+    void *operator new(std::size_t, A);
+  };
+  B *p = new ({123}) B;
+}

Modified: cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp?rev=208724&r1=208723&r2=208724&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp Tue May 13 14:56:21 2014
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify -std=c++11 %s
 
 #include <stddef.h>
 
@@ -10,3 +9,26 @@ void f() {
   // Expect no error in MSVC compatibility mode
   int *p = new(arbitrary) int[4];
 }
+
+class noncopyable { noncopyable(const noncopyable&); } extern nc; // expected-note {{here}}
+void *operator new[](size_t, noncopyable);
+void *operator new(size_t, const noncopyable&);
+void *q = new (nc) int[4]; // expected-error {{calling a private constructor}}
+
+struct bitfield { int n : 3; } bf; // expected-note {{here}}
+void *operator new[](size_t, int &);
+void *operator new(size_t, const int &);
+void *r = new (bf.n) int[4]; // expected-error {{non-const reference cannot bind to bit-field}}
+
+struct base {};
+struct derived : private base {} der; // expected-note {{here}}
+void *operator new[](size_t, base &);
+void *operator new(size_t, derived &);
+void *s = new (der) int[4]; // expected-error {{private}}
+
+struct explicit_ctor { explicit explicit_ctor(int); };
+struct explicit_ctor_tag {} ect;
+void *operator new[](size_t, explicit_ctor_tag, explicit_ctor);
+void *operator new(size_t, explicit_ctor_tag, int);
+void *t = new (ect, 0) int[4];
+void *u = new (ect, {0}) int[4];





More information about the cfe-commits mailing list