r224465 - Adding a -Wunused-value warning for expressions with side effects used in an unevaluated expression context, such as sizeof(), or decltype(). Also adds a similar warning when the expression passed to typeid() *is* evaluated, since it is equally likely that the user would expect the expression operand to be unevaluated in that case.

Aaron Ballman aaron at aaronballman.com
Fri Dec 19 07:05:03 PST 2014


On Fri, Dec 19, 2014 at 9:58 AM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
>
>
> On Fri Dec 19 2014 at 5:54:36 PM Aaron Ballman <aaron at aaronballman.com>
> wrote:
>>
>> On Fri, Dec 19, 2014 at 8:20 AM, Timur Iskhodzhanov <timurrrr at google.com>
>> wrote:
>> > I believe this is a false positive:
>> > -----------------------------------------
>> >   #include <typeinfo>
>> >   #include <vector>
>> >
>> >   struct A {
>> >     virtual ~A();
>> >   };
>> >
>> >   const char *foo(const std::vector<A*> &v) {
>> >     const std::type_info &t = typeid(*v[0]);
>> >     return t.name();
>> >   }
>> > -----------------------------------------
>>
>> That's not actually a false-positive because the result is a
>> polymorphic glvalue, which means operator[] is truly being called,
>> which can lead to some pretty unexpected results if you are not
>> anticipating it.
>
>
> Can you clarify what unexpected results do you mean?

Consider code like:


class C {
  C(); // Expensive
  char HugeBuffer[10240];

public:
  virtual ~C();

  static C *getInstance() {
    static C *c;
    if (!c)
      c = new C;
   return c;
  }
};

// ...
(void)typeid(C::getInstance());

This code will wind up calling C::getInstance, triggering the creation
of the underlying C pointer. It's equally likely that the programmer
is unaware of the fact that this winds up in an evaluated call, which
is why the warning exists in the first place. The rules for
potentially evaluating typeid aren't always clear to everyone.

>
>>
>> > This warning seems to be pretty annoying as it's on by default.
>>
>> I will be making a small change this morning to put this under its own
>> warning flag so that it can be turned off. I'm also exploring ways to
>> tweak the algorithm because there are some cases where this is
>> reasonable behavior. That being said, your code does have UB if
>> v.empty() == true, so it can catch bugs. ;-)
>
>
> (oh yeah, I was assuming the vector is not empty.  the warning is still
> there if I push_back a new object)

Correct, because we can't look into operator[]() to determine how safe
it is. I was more making the point that your code looks perfectly
reasonable and I think a lot of people would not realize that it
*could* trigger UB.

>>
>> > Is it possible to revert/disable and reland it gradually, making sure we
>> > don't get false positives along the way?
>> > or at least put it under a separate flag for the time being?
>>
>> Separate flag is incoming.
>
>
> Great!
> Will it be off by default?

No, it is on by default.

New flags are in r224578, as: -Wpotentially-evaluated-expression and
-Wunevaluated-expression

~Aaron

>
>>
>> ~Aaron
>>
>> >
>> > On Thu Dec 18 2014 at 9:01:03 PM Aaron Ballman <aaron at aaronballman.com>
>> > wrote:
>> >>
>> >> Author: aaronballman
>> >> Date: Wed Dec 17 15:57:17 2014
>> >> New Revision: 224465
>> >>
>> >> URL: http://llvm.org/viewvc/llvm-project?rev=224465&view=rev
>> >> Log:
>> >> Adding a -Wunused-value warning for expressions with side effects used
>> >> in
>> >> an unevaluated expression context, such as sizeof(), or decltype().
>> >> Also
>> >> adds a similar warning when the expression passed to typeid() *is*
>> >> evaluated, since it is equally likely that the user would expect the
>> >> expression operand to be unevaluated in that case.
>> >>
>> >> Modified:
>> >>     cfe/trunk/include/clang/AST/Expr.h
>> >>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> >>     cfe/trunk/include/clang/Sema/Sema.h
>> >>     cfe/trunk/lib/AST/Expr.cpp
>> >>     cfe/trunk/lib/Sema/SemaExpr.cpp
>> >>     cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> >>     cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
>> >>     cfe/trunk/lib/Sema/SemaType.cpp
>> >>
>> >>
>> >> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
>> >>     cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp
>> >>     cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp
>> >>     cfe/trunk/test/Sema/bitfield.c
>> >>     cfe/trunk/test/Sema/expr-comma-c99.c
>> >>     cfe/trunk/test/Sema/expr-comma.c
>> >>     cfe/trunk/test/Sema/warn-unused-value.c
>> >>     cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
>> >>     cfe/trunk/test/SemaCXX/runtimediag-ppe.cpp
>> >>     cfe/trunk/test/SemaCXX/undefined-internal.cpp
>> >>     cfe/trunk/test/SemaCXX/vararg-non-pod.cpp
>> >>     cfe/trunk/test/SemaCXX/warn-unused-result.cpp
>> >>     cfe/trunk/test/SemaCXX/warn-unused-value-cxx11.cpp
>> >>     cfe/trunk/test/SemaCXX/warn-unused-value.cpp
>> >>     cfe/trunk/test/SemaObjCXX/arc-ppe.mm
>> >>
>> >> Modified: cfe/trunk/include/clang/AST/Expr.h
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/include/clang/AST/Expr.h (original)
>> >> +++ cfe/trunk/include/clang/AST/Expr.h Wed Dec 17 15:57:17 2014
>> >> @@ -586,8 +586,13 @@ public:
>> >>
>> >>    /// HasSideEffects - This routine returns true for all those
>> >> expressions
>> >>    /// which have any effect other than producing a value. Example is a
>> >> function
>> >> -  /// call, volatile variable read, or throwing an exception.
>> >> -  bool HasSideEffects(const ASTContext &Ctx) const;
>> >> +  /// call, volatile variable read, or throwing an exception. If
>> >> +  /// IncludePossibleEffects is false, this call treats certain
>> >> expressions with
>> >> +  /// potential side effects (such as function call-like expressions,
>> >> +  /// instantiation-dependent expressions, or invocations from a
>> >> macro)
>> >> as not
>> >> +  /// having side effects.
>> >> +  bool HasSideEffects(const ASTContext &Ctx,
>> >> +                      bool IncludePossibleEffects = true) const;
>> >>
>> >>    /// \brief Determine whether this expression involves a call to any
>> >> function
>> >>    /// that is not trivial.
>> >>
>> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>> >> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Dec 17
>> >> 15:57:17 2014
>> >> @@ -6107,6 +6107,12 @@ def warn_unused_container_subscript_expr
>> >>  def warn_unused_call : Warning<
>> >>    "ignoring return value of function declared with %0 attribute">,
>> >>    InGroup<UnusedValue>;
>> >> +def warn_side_effects_unevaluated_context : Warning<
>> >> +  "expression with side effects has no effect in an unevaluated
>> >> context">,
>> >> +  InGroup<UnusedValue>;
>> >> +def warn_side_effects_typeid : Warning<
>> >> +  "expression with side effects will be evaluated despite being used
>> >> as
>> >> an "
>> >> +  "operand to 'typeid'">, InGroup<UnusedValue>;
>> >>  def warn_unused_result : Warning<
>> >>    "ignoring return value of function declared with warn_unused_result
>> >> "
>> >>    "attribute">, InGroup<DiagGroup<"unused-result">>;
>> >>
>> >> Modified: cfe/trunk/include/clang/Sema/Sema.h
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/include/clang/Sema/Sema.h (original)
>> >> +++ cfe/trunk/include/clang/Sema/Sema.h Wed Dec 17 15:57:17 2014
>> >> @@ -1399,7 +1399,10 @@ public:
>> >>                               const CXXScopeSpec &SS, QualType T);
>> >>
>> >>    QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
>> >> -  QualType BuildDecltypeType(Expr *E, SourceLocation Loc);
>> >> +  /// If AsUnevaluated is false, E is treated as though it were an
>> >> evaluated
>> >> +  /// context, such as when building a type for decltype(auto).
>> >> +  QualType BuildDecltypeType(Expr *E, SourceLocation Loc,
>> >> +                             bool AsUnevaluated = true);
>> >>    QualType BuildUnaryTransformType(QualType BaseType,
>> >>                                     UnaryTransformType::UTTKind UKind,
>> >>                                     SourceLocation Loc);
>> >>
>> >> Modified: cfe/trunk/lib/AST/Expr.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/lib/AST/Expr.cpp (original)
>> >> +++ cfe/trunk/lib/AST/Expr.cpp Wed Dec 17 15:57:17 2014
>> >> @@ -2866,9 +2866,16 @@ bool Expr::isConstantInitializer(ASTCont
>> >>    return false;
>> >>  }
>> >>
>> >> -bool Expr::HasSideEffects(const ASTContext &Ctx) const {
>> >> +bool Expr::HasSideEffects(const ASTContext &Ctx,
>> >> +                          bool IncludePossibleEffects) const {
>> >> +  // In circumstances where we care about definite side effects
>> >> instead
>> >> of
>> >> +  // potential side effects, we want to ignore expressions that are
>> >> part
>> >> of a
>> >> +  // macro expansion as a potential side effect.
>> >> +  if (!IncludePossibleEffects && getExprLoc().isMacroID())
>> >> +    return false;
>> >> +
>> >>    if (isInstantiationDependent())
>> >> -    return true;
>> >> +    return IncludePossibleEffects;
>> >>
>> >>    switch (getStmtClass()) {
>> >>    case NoStmtClass:
>> >> @@ -2921,21 +2928,27 @@ bool Expr::HasSideEffects(const ASTConte
>> >>      return false;
>> >>
>> >>    case CallExprClass:
>> >> +  case CXXOperatorCallExprClass:
>> >> +  case CXXMemberCallExprClass:
>> >> +  case CUDAKernelCallExprClass:
>> >> +  case BlockExprClass:
>> >> +  case CXXBindTemporaryExprClass:
>> >> +  case UserDefinedLiteralClass:
>> >> +    // We don't know a call definitely has side effects, but we can
>> >> check
>> >> the
>> >> +    // call's operands.
>> >> +    if (!IncludePossibleEffects)
>> >> +      break;
>> >> +    return true;
>> >> +
>> >>    case MSPropertyRefExprClass:
>> >>    case CompoundAssignOperatorClass:
>> >>    case VAArgExprClass:
>> >>    case AtomicExprClass:
>> >>    case StmtExprClass:
>> >> -  case CXXOperatorCallExprClass:
>> >> -  case CXXMemberCallExprClass:
>> >> -  case UserDefinedLiteralClass:
>> >>    case CXXThrowExprClass:
>> >>    case CXXNewExprClass:
>> >>    case CXXDeleteExprClass:
>> >>    case ExprWithCleanupsClass:
>> >> -  case CXXBindTemporaryExprClass:
>> >> -  case BlockExprClass:
>> >> -  case CUDAKernelCallExprClass:
>> >>      // These always have a side-effect.
>> >>      return true;
>> >>
>> >> @@ -2971,24 +2984,26 @@ bool Expr::HasSideEffects(const ASTConte
>> >>    case InitListExprClass:
>> >>      // FIXME: The children for an InitListExpr doesn't include the
>> >> array
>> >> filler.
>> >>      if (const Expr *E = cast<InitListExpr>(this)->getArrayFiller())
>> >> -      if (E->HasSideEffects(Ctx))
>> >> +      if (E->HasSideEffects(Ctx, IncludePossibleEffects))
>> >>          return true;
>> >>      break;
>> >>
>> >>    case GenericSelectionExprClass:
>> >>      return cast<GenericSelectionExpr>(this)->getResultExpr()->
>> >> -        HasSideEffects(Ctx);
>> >> +        HasSideEffects(Ctx, IncludePossibleEffects);
>> >>
>> >>    case ChooseExprClass:
>> >> -    return
>> >> cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(Ctx);
>> >> +    return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(
>> >> +        Ctx, IncludePossibleEffects);
>> >>
>> >>    case CXXDefaultArgExprClass:
>> >> -    return
>> >> cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(Ctx);
>> >> +    return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(
>> >> +        Ctx, IncludePossibleEffects);
>> >>
>> >>    case CXXDefaultInitExprClass: {
>> >>      const FieldDecl *FD = cast<CXXDefaultInitExpr>(this)->getField();
>> >>      if (const Expr *E = FD->getInClassInitializer())
>> >> -      return E->HasSideEffects(Ctx);
>> >> +      return E->HasSideEffects(Ctx, IncludePossibleEffects);
>> >>      // If we've not yet parsed the initializer, assume it has
>> >> side-effects.
>> >>      return true;
>> >>    }
>> >> @@ -3021,7 +3036,7 @@ bool Expr::HasSideEffects(const ASTConte
>> >>    case CXXConstructExprClass:
>> >>    case CXXTemporaryObjectExprClass: {
>> >>      const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
>> >> -    if (!CE->getConstructor()->isTrivial())
>> >> +    if (!CE->getConstructor()->isTrivial() && IncludePossibleEffects)
>> >>        return true;
>> >>      // A trivial constructor does not add any side-effects of its own.
>> >> Just look
>> >>      // at its arguments.
>> >> @@ -3049,7 +3064,7 @@ bool Expr::HasSideEffects(const ASTConte
>> >>        const Expr *Subexpr = *I;
>> >>        if (const OpaqueValueExpr *OVE =
>> >> dyn_cast<OpaqueValueExpr>(Subexpr))
>> >>          Subexpr = OVE->getSourceExpr();
>> >> -      if (Subexpr->HasSideEffects(Ctx))
>> >> +      if (Subexpr->HasSideEffects(Ctx, IncludePossibleEffects))
>> >>          return true;
>> >>      }
>> >>      return false;
>> >> @@ -3058,22 +3073,24 @@ bool Expr::HasSideEffects(const ASTConte
>> >>    case ObjCBoxedExprClass:
>> >>    case ObjCArrayLiteralClass:
>> >>    case ObjCDictionaryLiteralClass:
>> >> -  case ObjCMessageExprClass:
>> >>    case ObjCSelectorExprClass:
>> >>    case ObjCProtocolExprClass:
>> >> -  case ObjCPropertyRefExprClass:
>> >>    case ObjCIsaExprClass:
>> >>    case ObjCIndirectCopyRestoreExprClass:
>> >>    case ObjCSubscriptRefExprClass:
>> >>    case ObjCBridgedCastExprClass:
>> >> -    // FIXME: Classify these cases better.
>> >> -    return true;
>> >> +  case ObjCMessageExprClass:
>> >> +  case ObjCPropertyRefExprClass:
>> >> +  // FIXME: Classify these cases better.
>> >> +    if (IncludePossibleEffects)
>> >> +      return true;
>> >> +    break;
>> >>    }
>> >>
>> >>    // Recurse to children.
>> >>    for (const_child_range SubStmts = children(); SubStmts; ++SubStmts)
>> >>      if (const Stmt *S = *SubStmts)
>> >> -      if (cast<Expr>(S)->HasSideEffects(Ctx))
>> >> +      if (cast<Expr>(S)->HasSideEffects(Ctx, IncludePossibleEffects))
>> >>          return true;
>> >>
>> >>    return false;
>> >>
>> >> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
>> >> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Dec 17 15:57:17 2014
>> >> @@ -1290,6 +1290,13 @@ Sema::CreateGenericSelectionExpr(SourceL
>> >>      ControllingExpr = result.get();
>> >>    }
>> >>
>> >> +  // The controlling expression is an unevaluated operand, so side
>> >> effects are
>> >> +  // likely unintended.
>> >> +  if (ActiveTemplateInstantiations.empty() &&
>> >> +      ControllingExpr->HasSideEffects(Context, false))
>> >> +    Diag(ControllingExpr->getExprLoc(),
>> >> +         diag::warn_side_effects_unevaluated_context);
>> >> +
>> >>    bool TypeErrorFound = false,
>> >>         IsResultDependent = ControllingExpr->isTypeDependent(),
>> >>         ContainsUnexpandedParameterPack
>> >> @@ -3525,6 +3532,12 @@ bool Sema::CheckUnaryExprOrTypeTraitOper
>> >>      return true;
>> >>    }
>> >>
>> >> +  // The operand for sizeof and alignof is in an unevaluated
>> >> expression
>> >> context,
>> >> +  // so side effects could result in unintended consequences.
>> >> +  if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf) &&
>> >> +      ActiveTemplateInstantiations.empty() &&
>> >> E->HasSideEffects(Context,
>> >> false))
>> >> +    Diag(E->getExprLoc(),
>> >> diag::warn_side_effects_unevaluated_context);
>> >> +
>> >>    if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
>> >>                                         E->getSourceRange(), ExprKind))
>> >>      return true;
>> >>
>> >> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
>> >> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Dec 17 15:57:17 2014
>> >> @@ -396,6 +396,7 @@ ExprResult Sema::BuildCXXTypeId(QualType
>> >>                                  SourceLocation TypeidLoc,
>> >>                                  Expr *E,
>> >>                                  SourceLocation RParenLoc) {
>> >> +  bool WasEvaluated = false;
>> >>    if (E && !E->isTypeDependent()) {
>> >>      if (E->getType()->isPlaceholderType()) {
>> >>        ExprResult result = CheckPlaceholderExpr(E);
>> >> @@ -425,6 +426,7 @@ ExprResult Sema::BuildCXXTypeId(QualType
>> >>
>> >>          // We require a vtable to query the type at run time.
>> >>          MarkVTableUsed(TypeidLoc, RecordD);
>> >> +        WasEvaluated = true;
>> >>        }
>> >>      }
>> >>
>> >> @@ -444,6 +446,14 @@ ExprResult Sema::BuildCXXTypeId(QualType
>> >>    if (E->getType()->isVariablyModifiedType())
>> >>      return ExprError(Diag(TypeidLoc,
>> >> diag::err_variably_modified_typeid)
>> >>                       << E->getType());
>> >> +  else if (ActiveTemplateInstantiations.empty() &&
>> >> +           E->HasSideEffects(Context, WasEvaluated)) {
>> >> +    // The expression operand for typeid is in an unevaluated
>> >> expression
>> >> +    // context, so side effects could result in unintended
>> >> consequences.
>> >> +    Diag(E->getExprLoc(), WasEvaluated
>> >> +                              ? diag::warn_side_effects_typeid
>> >> +                              :
>> >> diag::warn_side_effects_unevaluated_context);
>> >> +  }
>> >>
>> >>    return new (Context) CXXTypeidExpr(TypeInfoType.withConst(), E,
>> >>                                       SourceRange(TypeidLoc,
>> >> RParenLoc));
>> >> @@ -5622,7 +5632,8 @@ ExprResult Sema::ActOnPseudoDestructorEx
>> >>    if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
>> >>      return ExprError();
>> >>
>> >> -  QualType T = BuildDecltypeType(DS.getRepAsExpr(),
>> >> DS.getTypeSpecTypeLoc());
>> >> +  QualType T = BuildDecltypeType(DS.getRepAsExpr(),
>> >> DS.getTypeSpecTypeLoc(),
>> >> +                                 false);
>> >>
>> >>    TypeLocBuilder TLB;
>> >>    DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
>> >> @@ -5690,6 +5701,13 @@ ExprResult Sema::BuildCXXMemberCallExpr(
>> >>
>> >>  ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr
>> >> *Operand,
>> >>                                        SourceLocation RParen) {
>> >> +  if (ActiveTemplateInstantiations.empty() &&
>> >> +      Operand->HasSideEffects(Context, false)) {
>> >> +    // The expression operand for noexcept is in an unevaluated
>> >> expression
>> >> +    // context, so side effects could result in unintended
>> >> consequences.
>> >> +    Diag(Operand->getExprLoc(),
>> >> diag::warn_side_effects_unevaluated_context);
>> >> +  }
>> >> +
>> >>    CanThrowResult CanThrow = canThrow(Operand);
>> >>    return new (Context)
>> >>        CXXNoexceptExpr(Context.BoolTy, Operand, CanThrow, KeyLoc,
>> >> RParen);
>> >>
>> >> Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
>> >> +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Dec 17 15:57:17
>> >> 2014
>> >> @@ -3989,7 +3989,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
>> >>          return DAR_FailedAlreadyDiagnosed;
>> >>        }
>> >>
>> >> -      QualType Deduced = BuildDecltypeType(Init, Init->getLocStart());
>> >> +      QualType Deduced = BuildDecltypeType(Init, Init->getLocStart(),
>> >> false);
>> >>        // FIXME: Support a non-canonical deduced type for 'auto'.
>> >>        Deduced = Context.getCanonicalType(Deduced);
>> >>        Result = SubstituteAutoTransform(*this, Deduced).Apply(Type);
>> >>
>> >> Modified: cfe/trunk/lib/Sema/SemaType.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
>> >> +++ cfe/trunk/lib/Sema/SemaType.cpp Wed Dec 17 15:57:17 2014
>> >> @@ -5518,11 +5518,19 @@ static QualType getDecltypeForExpr(Sema
>> >>    return T;
>> >>  }
>> >>
>> >> -QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
>> >> +QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
>> >> +                                 bool AsUnevaluated) {
>> >>    ExprResult ER = CheckPlaceholderExpr(E);
>> >>    if (ER.isInvalid()) return QualType();
>> >>    E = ER.get();
>> >>
>> >> +  if (AsUnevaluated && ActiveTemplateInstantiations.empty() &&
>> >> +      E->HasSideEffects(Context, false)) {
>> >> +    // The expression operand for decltype is in an unevaluated
>> >> expression
>> >> +    // context, so side effects could result in unintended
>> >> consequences.
>> >> +    Diag(E->getExprLoc(),
>> >> diag::warn_side_effects_unevaluated_context);
>> >> +  }
>> >> +
>> >>    return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
>> >>  }
>> >>
>> >>
>> >> Modified:
>> >>
>> >> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> ---
>> >>
>> >> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
>> >> (original)
>> >> +++
>> >>
>> >> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
>> >> Wed Dec 17 15:57:17 2014
>> >> @@ -18,7 +18,7 @@ void unevaluated_operand(P &p, int i) {
>> >>    // FIXME: this should only emit one error.
>> >>    int i2 = sizeof([](auto a, auto b)->void{}(3, '4')); //
>> >> expected-error{{lambda expression in an unevaluated operand}} \
>> >>                                                         //
>> >> expected-error{{invalid application of 'sizeof'}}
>> >> -  const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p;
>> >> return p; }(i));
>> >> +  const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p;
>> >> return p; }(i)); // expected-warning {{expression with side effects
>> >> will be
>> >> evaluated despite being used as an operand to 'typeid'}}
>> >>    const std::type_info &ti2 = typeid([](auto) -> int { return i;
>> >> }(i));
>> >> // expected-error{{lambda expression in an unevaluated operand}}\
>> >>
>> >> // expected-error{{cannot be implicitly captured}}\
>> >>
>> >> // expected-note{{begins here}}
>> >>
>> >> Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp
>> >> (original)
>> >> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp Wed Dec
>> >> 17
>> >> 15:57:17 2014
>> >> @@ -1,4 +1,4 @@
>> >> -// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
>> >> +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-unused-value %s
>> >> -verify
>> >>
>> >>  // prvalue
>> >>  void prvalue() {
>> >>
>> >> Modified:
>> >> cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp
>> >> (original)
>> >> +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp Wed
>> >> Dec 17 15:57:17 2014
>> >> @@ -1,4 +1,4 @@
>> >> -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify
>> >> -std=c++11 -fms-extensions -Wno-delete-incomplete %s
>> >> +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify
>> >> -std=c++11 -fms-extensions -Wno-delete-incomplete -Wno-unused-value %s
>> >>  // expected-no-diagnostics
>> >>
>> >>  #define P(e) static_assert(noexcept(e), "expected nothrow")
>> >>
>> >> Modified: cfe/trunk/test/Sema/bitfield.c
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/bitfield.c?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/Sema/bitfield.c (original)
>> >> +++ cfe/trunk/test/Sema/bitfield.c Wed Dec 17 15:57:17 2014
>> >> @@ -1,4 +1,5 @@
>> >> -// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c11
>> >> +// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c11 -Wno-unused-value
>> >> +
>> >>  enum e0; // expected-note{{forward declaration of 'enum e0'}}
>> >>
>> >>  struct a {
>> >>
>> >> Modified: cfe/trunk/test/Sema/expr-comma-c99.c
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/expr-comma-c99.c?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/Sema/expr-comma-c99.c (original)
>> >> +++ cfe/trunk/test/Sema/expr-comma-c99.c Wed Dec 17 15:57:17 2014
>> >> @@ -1,5 +1,4 @@
>> >>  // RUN: %clang_cc1 %s -fsyntax-only -verify -std=c99
>> >> -Wno-sizeof-array-decay
>> >> -// expected-no-diagnostics
>> >>  // rdar://6095180
>> >>
>> >>  struct s { char c[17]; };
>> >> @@ -14,5 +13,5 @@ int B[sizeof((a.c)) == 17 ? 1 : -1];
>> >>  // comma does array/function promotion in c99.
>> >>  int X[sizeof(0, (foo().c)) == sizeof(char*) ? 1 : -1];
>> >>  int Y[sizeof(0, (a,b).c) == sizeof(char*) ? 1 : -1];
>> >> -int Z[sizeof(0, (a=b).c) == sizeof(char*) ? 1 : -1];
>> >> +int Z[sizeof(0, (a=b).c) == sizeof(char*) ? 1 : -1]; //
>> >> expected-warning
>> >> {{expression with side effects has no effect in an unevaluated
>> >> context}}
>> >>
>> >>
>> >> Modified: cfe/trunk/test/Sema/expr-comma.c
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/expr-comma.c?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/Sema/expr-comma.c (original)
>> >> +++ cfe/trunk/test/Sema/expr-comma.c Wed Dec 17 15:57:17 2014
>> >> @@ -1,5 +1,4 @@
>> >>  // RUN: %clang_cc1 %s -fsyntax-only -verify -std=c89
>> >> -Wno-sizeof-array-decay
>> >> -// expected-no-diagnostics
>> >>  // rdar://6095180
>> >>
>> >>  struct s { char c[17]; };
>> >> @@ -15,4 +14,4 @@ int B[sizeof((a.c)) == 17 ? 1 : -1];
>> >>  int W[sizeof(0, a.c) == sizeof(char*) ? 1 : -1];
>> >>  int X[sizeof(0, (foo().c)) == 17 ? 1 : -1];
>> >>  int Y[sizeof(0, (a,b).c) == 17 ? 1 : -1];
>> >> -int Z[sizeof(0, (a=b).c) == 17 ? 1 : -1];
>> >> +int Z[sizeof(0, (a=b).c) == 17 ? 1 : -1]; // expected-warning
>> >> {{expression with side effects has no effect in an unevaluated
>> >> context}}
>> >>
>> >> Modified: cfe/trunk/test/Sema/warn-unused-value.c
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-unused-value.c?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/Sema/warn-unused-value.c (original)
>> >> +++ cfe/trunk/test/Sema/warn-unused-value.c Wed Dec 17 15:57:17 2014
>> >> @@ -1,6 +1,6 @@
>> >> -// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -Wunused-label
>> >> %s
>> >> -// RUN: %clang_cc1 -fsyntax-only -verify -Wunused %s
>> >> -// RUN: %clang_cc1 -fsyntax-only -verify -Wall %s
>> >> +// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wunused-value
>> >> -Wunused-label %s
>> >> +// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wunused %s
>> >> +// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wall %s
>> >>
>> >>  int i = 0;
>> >>  int j = 0;
>> >> @@ -88,3 +88,22 @@ void f1(struct s0 *a) {
>> >>    // rdar://8139785
>> >>    f0((int)(a->f0 + 1, 10)); // expected-warning {{expression result
>> >> unused}}
>> >>  }
>> >> +
>> >> +void blah(int a);
>> >> +#define GenTest(x) _Generic(x, default : blah)(x)
>> >> +
>> >> +void unevaluated_operands(void) {
>> >> +  int val = 0;
>> >> +
>> >> +  (void)sizeof(++val); // expected-warning {{expression with side
>> >> effects
>> >> has no effect in an unevaluated context}}
>> >> +  (void)_Generic(val++, default : 0); // expected-warning {{expression
>> >> with side effects has no effect in an unevaluated context}}
>> >> +  (void)_Alignof(val++);  // expected-warning {{expression with side
>> >> effects has no effect in an unevaluated context}} expected-warning
>> >> {{'_Alignof' applied to an expression is a GNU extension}}
>> >> +
>> >> +  // VLAs can have side effects so long as it's part of the type and
>> >> not
>> >> +  // an expression.
>> >> +  (void)sizeof(int[++val]); // Ok
>> >> +  (void)_Alignof(int[++val]); // Ok
>> >> +
>> >> +  // Side effects as part of macro expansion are ok.
>> >> +  GenTest(val++);
>> >> +}
>> >>
>> >> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
>> >> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Wed Dec 17
>> >> 15:57:17 2014
>> >> @@ -1613,7 +1613,8 @@ namespace TypeId {
>> >>    A &g();
>> >>    constexpr auto &x = typeid(f());
>> >>    constexpr auto &y = typeid(g()); // expected-error{{constant
>> >> expression}} \
>> >> -  // expected-note{{typeid applied to expression of polymorphic type
>> >> 'TypeId::A' is not allowed in a constant expression}}
>> >> +  // expected-note{{typeid applied to expression of polymorphic type
>> >> 'TypeId::A' is not allowed in a constant expression}} \
>> >> +  // expected-warning {{expression with side effects will be evaluated
>> >> despite being used as an operand to 'typeid'}}
>> >>  }
>> >>
>> >>  namespace PR14203 {
>> >>
>> >> Modified: cfe/trunk/test/SemaCXX/runtimediag-ppe.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/runtimediag-ppe.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/SemaCXX/runtimediag-ppe.cpp (original)
>> >> +++ cfe/trunk/test/SemaCXX/runtimediag-ppe.cpp Wed Dec 17 15:57:17 2014
>> >> @@ -1,4 +1,4 @@
>> >> -// RUN: %clang_cc1 -fsyntax-only -verify %s
>> >> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused-value %s
>> >>
>> >>  // Make sure diagnostics that we don't print based on runtime control
>> >>  // flow are delayed correctly in cases where we can't immediately tell
>> >> whether
>> >>
>> >> Modified: cfe/trunk/test/SemaCXX/undefined-internal.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/undefined-internal.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/SemaCXX/undefined-internal.cpp (original)
>> >> +++ cfe/trunk/test/SemaCXX/undefined-internal.cpp Wed Dec 17 15:57:17
>> >> 2014
>> >> @@ -163,7 +163,7 @@ namespace cxx11_odr_rules {
>> >>
>> >>      // Check that the checks work with unevaluated contexts
>> >>      (void)sizeof(p(A::used1));
>> >> -    (void)typeid(p(A::used1)); // xpected-note {{used here}}
>> >> +    (void)typeid(p(A::used1)); // expected-warning {{expression with
>> >> side
>> >> effects will be evaluated despite being used as an operand to
>> >> 'typeid'}}
>> >> xpected-note {{used here}}
>> >>
>> >>      // Misc other testing
>> >>      a(A::unused, 1 ? A::used2 : A::used2); // xpected-note {{used
>> >> here}}
>> >>
>> >> Modified: cfe/trunk/test/SemaCXX/vararg-non-pod.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/vararg-non-pod.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/SemaCXX/vararg-non-pod.cpp (original)
>> >> +++ cfe/trunk/test/SemaCXX/vararg-non-pod.cpp Wed Dec 17 15:57:17 2014
>> >> @@ -103,7 +103,7 @@ Base &get_base(...);
>> >>  int eat_base(...);
>> >>
>> >>  void test_typeid(Base &base) {
>> >> -  (void)typeid(get_base(base)); // expected-warning{{cannot pass
>> >> object
>> >> of non-POD type 'Base' through variadic function; call will abort at
>> >> runtime}}
>> >> +  (void)typeid(get_base(base)); // expected-warning{{cannot pass
>> >> object
>> >> of non-POD type 'Base' through variadic function; call will abort at
>> >> runtime}} expected-warning{{expression with side effects will be
>> >> evaluated
>> >> despite being used as an operand to 'typeid'}}
>> >>    (void)typeid(eat_base(base)); // okay
>> >>  }
>> >>
>> >>
>> >> Modified: cfe/trunk/test/SemaCXX/warn-unused-result.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-result.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/SemaCXX/warn-unused-result.cpp (original)
>> >> +++ cfe/trunk/test/SemaCXX/warn-unused-result.cpp Wed Dec 17 15:57:17
>> >> 2014
>> >> @@ -132,7 +132,7 @@ void g() {
>> >>    D d;
>> >>    C c;
>> >>    (void)typeid(f(), c); // Should not warn.
>> >> -  (void)typeid(f(), d); // expected-warning {{ignoring return value}}
>> >> +  (void)typeid(f(), d); // expected-warning {{ignoring return value}}
>> >> expected-warning {{expression with side effects will be evaluated
>> >> despite
>> >> being used as an operand to 'typeid'}}
>> >>
>> >>    // The sizeof expression operand is never evaluated.
>> >>    (void)sizeof(f(), c); // Should not warn.
>> >>
>> >> Modified: cfe/trunk/test/SemaCXX/warn-unused-value-cxx11.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-value-cxx11.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/SemaCXX/warn-unused-value-cxx11.cpp (original)
>> >> +++ cfe/trunk/test/SemaCXX/warn-unused-value-cxx11.cpp Wed Dec 17
>> >> 15:57:17
>> >> 2014
>> >> @@ -1,5 +1,4 @@
>> >>  // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wunused-value %s
>> >> -// expected-no-diagnostics
>> >>
>> >>  void f() __attribute__((const));
>> >>
>> >> @@ -13,4 +12,33 @@ auto foo(T) -> decltype(f(), bool()) { /
>> >>  void g() {
>> >>    foo(1);
>> >>  }
>> >> +
>> >> +void h() {
>> >> +  int i = 0;
>> >> +  (void)noexcept(++i); // expected-warning {{expression with side
>> >> effects
>> >> has no effect in an unevaluated context}}
>> >> +  decltype(i++) j = 0; // expected-warning {{expression with side
>> >> effects
>> >> has no effect in an unevaluated context}}
>> >>  }
>> >> +
>> >> +struct S {
>> >> +  S operator++(int);
>> >> +  S(int i);
>> >> +  S();
>> >> +
>> >> +  int& f();
>> >> +  S g();
>> >> +};
>> >> +
>> >> +void j() {
>> >> +  S s;
>> >> +  int i = 0;
>> >> +  (void)noexcept(s++); // Ok
>> >> +  (void)noexcept(i++); // expected-warning {{expression with side
>> >> effects
>> >> has no effect in an unevaluated context}}
>> >> +  (void)noexcept(i = 5); // expected-warning {{expression with side
>> >> effects has no effect in an unevaluated context}}
>> >> +  (void)noexcept(s = 5); // Ok
>> >> +
>> >> +  (void)sizeof(s.f()); // Ok
>> >> +  (void)sizeof(s.f() = 5); // expected-warning {{expression with side
>> >> effects has no effect in an unevaluated context}}
>> >> +  (void)noexcept(s.g() = 5); // Ok
>> >> +}
>> >> +
>> >> +}
>> >> \ No newline at end of file
>> >>
>> >> Modified: cfe/trunk/test/SemaCXX/warn-unused-value.cpp
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-value.cpp?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/SemaCXX/warn-unused-value.cpp (original)
>> >> +++ cfe/trunk/test/SemaCXX/warn-unused-value.cpp Wed Dec 17 15:57:17
>> >> 2014
>> >> @@ -39,13 +39,13 @@ namespace test2 {
>> >>          void method() const {
>> >>           X* x;
>> >>           &x[0];  // expected-warning {{expression result unused}}
>> >> -        }
>> >> +        }
>> >>        };
>> >>        typedef basic_string<char> string;
>> >> -      void func(const std::string& str) {
>> >> +      void func(const std::string& str) {
>> >>          str.method();  // expected-note {{in instantiation of member
>> >> function}}
>> >>        }
>> >> -    }
>> >> +    }
>> >>    }
>> >>  }
>> >>
>> >> @@ -69,3 +69,30 @@ void f() {
>> >>    Unused(1, 1); // expected-warning {{expression result unused}}
>> >>  }
>> >>  }
>> >> +
>> >> +namespace std {
>> >> +  struct type_info {};
>> >> +}
>> >> +
>> >> +namespace test4 {
>> >> +struct Good { Good &f(); };
>> >> +struct Bad { virtual Bad& f(); };
>> >> +
>> >> +void f() {
>> >> +  int i = 0;
>> >> +  (void)typeid(++i); // expected-warning {{expression with side
>> >> effects
>> >> has no effect in an unevaluated context}}
>> >> +
>> >> +  Good g;
>> >> +  (void)typeid(g.f()); // Ok; not a polymorphic use of a glvalue.
>> >> +
>> >> +  // This is a polymorphic use of a glvalue, which results in the
>> >> typeid
>> >> being
>> >> +  // evaluated instead of unevaluated.
>> >> +  Bad b;
>> >> +  (void)typeid(b.f()); // expected-warning {{expression with side
>> >> effects
>> >> will be evaluated despite being used as an operand to 'typeid'}}
>> >> +
>> >> +  // A dereference of a volatile pointer is a side effecting
>> >> operation,
>> >> despite
>> >> +  // it being a reasonable operation.
>> >> +  int * volatile x;
>> >> +  (void)sizeof(*x); // expected-warning {{expression with side effects
>> >> has no effect in an unevaluated context}}
>> >> +}
>> >> +}
>> >>
>> >> Modified: cfe/trunk/test/SemaObjCXX/arc-ppe.mm
>> >> URL:
>> >>
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-ppe.mm?rev=224465&r1=224464&r2=224465&view=diff
>> >>
>> >>
>> >> ==============================================================================
>> >> --- cfe/trunk/test/SemaObjCXX/arc-ppe.mm (original)
>> >> +++ cfe/trunk/test/SemaObjCXX/arc-ppe.mm Wed Dec 17 15:57:17 2014
>> >> @@ -13,4 +13,4 @@ void test1() { (void)typeid(NP((void*)(i
>> >>
>> >>  class Poly { virtual ~Poly(); };
>> >>  Poly& P(void*);
>> >> -void test2() { (void)typeid(P((void*)(id*)0)); } // expected-error
>> >> {{pointer to non-const type 'id'}}
>> >> +void test2() { (void)typeid(P((void*)(id*)0)); } // expected-error
>> >> {{pointer to non-const type 'id'}} expected-warning {{expression with
>> >> side
>> >> effects will be evaluated despite being used as an operand to
>> >> 'typeid'}}
>> >>
>> >>
>> >> _______________________________________________
>> >> cfe-commits mailing list
>> >> cfe-commits at cs.uiuc.edu
>> >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list