Gently ping. > On May 27, 2015, at 10:44 AM, Ettore Speziale <[email protected]> > wrote: > > Hello Nick, > > thanks for taking a look at the patch. > >> I think this will cause the enable_if expression to be evaluated multiple >> times if the expression is not dependent but appertains to a function >> template, such as: >> >> template <typename T> void foo(int i, T t) __attribute__((enable_if(i==0, >> ""))) {} >> >> I'm not sure how to fix that without hoisting it up to ActOnCallExpr? Could >> you check whether this is a real problem? > > I tried to run this small example: > > // RUN: clang++ -emit-llvm -S -o - test.cpp > > struct foo { > template <typename T> > int f(int i, T t) __attribute__((enable_if(i == 0, "only when 'i' is > zero"))); > > template <typename T> > int g(int i, float j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > template <typename T> > int g(int i, double j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > }; > > int bar(foo in, int ti, float tf) { > return in.f(1, ti) + in.f(1, tf); > } > > int baz(foo in, float fj, double dj, int ti, float tf) { > return in.g(1, fj, ti) + in.g(1, fj, tf) + in.g(1, dj, ti) + in.g(1, dj, tf); > } > > With a modified version of clang that dump the expression just before it is > being computed in CheckEnableIf: > > diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp > index 95af64e..361a4f3 100644 > --- a/lib/Sema/SemaOverload.cpp > +++ b/lib/Sema/SemaOverload.cpp > @@ -5887,6 +5887,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl > *Function, ArrayRef<Expr *> Args, > continue; > } > > + llvm::errs() << "EVALUATE EXPR\n"; EIA->getCond()->dump(); > if (!EIA->getCond()->EvaluateWithSubstitution( > Result, Context, Function, llvm::makeArrayRef(ConvertedArgs))) { > if (!ContainsValueDependentExpr) > > The bar function exercise the code in my patch, the baz function exercise > existing code. > > This is what I get: > > ┌─[ettore@vesta] - [/tmp] - [2015-05-27 10:11:24] > └─[1] <> clang++ -emit-llvm -S -o - test.cpp > EVALUATE EXPR > BinaryOperator 0x7fc06507e2c8 '_Bool' '==' > |-ImplicitCastExpr 0x7fc06507e2b0 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc06507e288 'int' lvalue ParmVar 0x7fc06507df98 'i' 'int' > `-IntegerLiteral 0x7fc06507be00 'int' 0 > test.cpp:13:13: error: no matching member function for call to 'f' > return in.f(1, ti) + in.f(1, tf); > ~~~^ > test.cpp:4:7: note: candidate disabled: only when 'i' is zero > int f(int i, T t) __attribute__((enable_if(i == 0, "only when 'i' is > zero"))); > ^ ~~~~~~ > EVALUATE EXPR > BinaryOperator 0x7fc06507e780 '_Bool' '==' > |-ImplicitCastExpr 0x7fc06507e768 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc06507e740 'int' lvalue ParmVar 0x7fc06507e480 'i' 'int' > `-IntegerLiteral 0x7fc06507be00 'int' 0 > test.cpp:13:27: error: no matching member function for call to 'f' > return in.f(1, ti) + in.f(1, tf); > ~~~^ > test.cpp:4:7: note: candidate disabled: only when 'i' is zero > int f(int i, T t) __attribute__((enable_if(i == 0, "only when 'i' is > zero"))); > ^ ~~~~~~ > EVALUATE EXPR > BinaryOperator 0x7fc06507f188 '_Bool' '==' > |-ImplicitCastExpr 0x7fc06507f170 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc06507f148 'int' lvalue ParmVar 0x7fc06507ee00 'i' 'int' > `-IntegerLiteral 0x7fc06507c338 'int' 0 > EVALUATE EXPR > BinaryOperator 0x7fc06507f698 '_Bool' '==' > |-ImplicitCastExpr 0x7fc06507f680 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc06507f658 'int' lvalue ParmVar 0x7fc06507f308 'i' 'int' > `-IntegerLiteral 0x7fc06507c828 'int' 0 > test.cpp:17:13: error: no matching member function for call to 'g' > return in.g(1, fj, ti) + in.g(1, fj, tf) + in.g(1, dj, ti) + in.g(1, dj, tf); > ~~~^ > test.cpp:7:7: note: candidate disabled: only when 'i' is zero > int g(int i, float j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > ^ ~~~~~~ > test.cpp:9:7: note: candidate disabled: only when 'i' is zero > int g(int i, double j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > ^ ~~~~~~ > EVALUATE EXPR > BinaryOperator 0x7fc06507fc38 '_Bool' '==' > |-ImplicitCastExpr 0x7fc06507fc20 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc06507fbf8 'int' lvalue ParmVar 0x7fc06507f8b0 'i' 'int' > `-IntegerLiteral 0x7fc06507c338 'int' 0 > EVALUATE EXPR > BinaryOperator 0x7fc0650804c8 '_Bool' '==' > |-ImplicitCastExpr 0x7fc0650804b0 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc065080488 'int' lvalue ParmVar 0x7fc06507fd30 'i' 'int' > `-IntegerLiteral 0x7fc06507c828 'int' 0 > test.cpp:17:31: error: no matching member function for call to 'g' > return in.g(1, fj, ti) + in.g(1, fj, tf) + in.g(1, dj, ti) + in.g(1, dj, tf); > ~~~^ > test.cpp:7:7: note: candidate disabled: only when 'i' is zero > int g(int i, float j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > ^ ~~~~~~ > test.cpp:9:7: note: candidate disabled: only when 'i' is zero > int g(int i, double j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > ^ ~~~~~~ > EVALUATE EXPR > BinaryOperator 0x7fc06507f188 '_Bool' '==' > |-ImplicitCastExpr 0x7fc06507f170 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc06507f148 'int' lvalue ParmVar 0x7fc06507ee00 'i' 'int' > `-IntegerLiteral 0x7fc06507c338 'int' 0 > EVALUATE EXPR > BinaryOperator 0x7fc06507f698 '_Bool' '==' > |-ImplicitCastExpr 0x7fc06507f680 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc06507f658 'int' lvalue ParmVar 0x7fc06507f308 'i' 'int' > `-IntegerLiteral 0x7fc06507c828 'int' 0 > test.cpp:17:49: error: no matching member function for call to 'g' > return in.g(1, fj, ti) + in.g(1, fj, tf) + in.g(1, dj, ti) + in.g(1, dj, tf); > ~~~^ > test.cpp:7:7: note: candidate disabled: only when 'i' is zero > int g(int i, float j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > ^ ~~~~~~ > test.cpp:9:7: note: candidate disabled: only when 'i' is zero > int g(int i, double j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > ^ ~~~~~~ > EVALUATE EXPR > BinaryOperator 0x7fc06507fc38 '_Bool' '==' > |-ImplicitCastExpr 0x7fc06507fc20 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc06507fbf8 'int' lvalue ParmVar 0x7fc06507f8b0 'i' 'int' > `-IntegerLiteral 0x7fc06507c338 'int' 0 > EVALUATE EXPR > BinaryOperator 0x7fc0650804c8 '_Bool' '==' > |-ImplicitCastExpr 0x7fc0650804b0 'int' <LValueToRValue> > | `-DeclRefExpr 0x7fc065080488 'int' lvalue ParmVar 0x7fc06507fd30 'i' 'int' > `-IntegerLiteral 0x7fc06507c828 'int' 0 > test.cpp:17:67: error: no matching member function for call to 'g' > return in.g(1, fj, ti) + in.g(1, fj, tf) + in.g(1, dj, ti) + in.g(1, dj, tf); > ~~~^ > test.cpp:7:7: note: candidate disabled: only when 'i' is zero > int g(int i, float j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > ^ ~~~~~~ > test.cpp:9:7: note: candidate disabled: only when 'i' is zero > int g(int i, double j, T t) __attribute__((enable_if(i == 0, "only when 'i' > is zero"))); > ^ ~~~~~~ > 6 errors generated. > > I can see the expression being evaluated once for each call to f, and twice > for each call to g, as it has two overloads. So it seems that my patch and > the current implementation works in the same way from this point of view. > > Did I understand correctly? > > Thanks, > Ettore Speziale
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
