ehsan updated this revision to Diff 47056.
ehsan added a comment.
Updating based on the LLVM side changes.
http://reviews.llvm.org/D16761
Files:
docs/ClangPlugins.rst
examples/PrintFunctionNames/PrintFunctionNames.cpp
include/clang/Basic/DiagnosticASTKinds.td
lib/AST/ExprConstant.cpp
lib/FrontendTool/ExecuteCompilerInvocation.cpp
test/CodeGenCXX/static-init-msvc.cpp
test/Frontend/plugins.c
test/lit.cfg
Index: test/lit.cfg
===================================================================
--- test/lit.cfg
+++ test/lit.cfg
@@ -196,7 +196,7 @@
# Plugins (loadable modules)
# TODO: This should be supplied by Makefile or autoconf.
-if sys.platform in ['win32', 'cygwin']:
+if sys.platform in ['cygwin']:
has_plugins = (config.enable_shared == 1)
else:
has_plugins = True
Index: test/Frontend/plugins.c
===================================================================
--- test/Frontend/plugins.c
+++ test/Frontend/plugins.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -load %llvmshlibdir/PrintFunctionNames%pluginext -plugin print-fns %s 2>&1 | FileCheck %s
+// RUN: %clang_cl -Xclang -load -Xclang %llvmshlibdir/PrintFunctionNames%pluginext -Xclang -plugin -Xclang print-fns %s 2>&1 | FileCheck %s
// REQUIRES: plugins, examples
// CHECK: top-level-decl: "x"
Index: test/CodeGenCXX/static-init-msvc.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/static-init-msvc.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc -fms-extensions -emit-llvm -O0 -w -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -O0 -w -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -fms-extensions -emit-llvm -O0 -w -o - %s | FileCheck %s --check-prefix GNU
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -fms-extensions -emit-llvm -O0 -w -o - %s | FileCheck %s --check-prefix GNU
+
+void fun_and() {
+// CHECK-LABEL: @"\01?fun_and@@YAXXZ"()
+// GNU-LABEL: @_Z7fun_andv()
+ static int k;
+ static const int foo = 0 && k;
+// CHECK: init:
+// CHECK-NEXT: store i32 0, i32* @"\01?foo@?1??fun_and@@YAXXZ@4HB", align 4
+// GNU: entry:
+// GNU-NEXT: ret void
+}
+
+void fun_or() {
+// CHECK-LABEL: @"\01?fun_or@@YAXXZ"()
+// GNU-LABEL: @_Z6fun_orv()
+ static int k;
+ static const int foo = 1 || k;
+// CHECK: init:
+// CHECK-NEXT: store i32 1, i32* @"\01?foo@?1??fun_or@@YAXXZ@4HB", align 4
+// GNU: entry:
+// GNU-NEXT: ret void
+}
+
+void fun_comma() {
+// CHECK-LABEL: @"\01?fun_comma@@YAXXZ"()
+// GNU-LABEL: @_Z9fun_commav()
+ static int k;
+ static const int foo = (k, 0);
+// CHECK: init:
+// CHECK-NEXT: store i32 0, i32* @"\01?foo@?1??fun_comma@@YAXXZ@4HB", align 4
+// GNU: entry:
+// GNU-NEXT: ret void
+}
+
+void fun_cond() {
+// CHECK-LABEL: @"\01?fun_cond@@YAXXZ"()
+// GNU-LABEL: @_Z8fun_condv()
+ static int k;
+ static const int foo = true ? 0 : k;
+// CHECK: init:
+// CHECK-NEXT: store i32 0, i32* @"\01?foo@?1??fun_cond@@YAXXZ@4HB", align 4
+// GNU: entry:
+// GNU-NEXT: ret void
+}
Index: lib/FrontendTool/ExecuteCompilerInvocation.cpp
===================================================================
--- lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -184,9 +184,16 @@
e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) {
const std::string &Path = Clang->getFrontendOpts().Plugins[i];
std::string Error;
- if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
+ llvm::sys::DynamicLibrary DL(
+ llvm::sys::DynamicLibrary::getPermanentLibrary(Path.c_str(), &Error));
+ if (DL.isValid()) {
+ // On Windows, we need to import the plugin front-end action
+ // dynamically.
+ LLVM_IMPORT_REGISTRY(FrontendPluginRegistry, DL);
+ } else {
Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin)
<< Path << Error;
+ }
}
// Honor -mllvm.
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -477,6 +477,19 @@
/// fold (not just why it's not strictly a constant expression)?
bool HasFoldFailureDiagnostic;
+ /// \brief True if we need to obey the Microsoft ABI. This affects whether
+ /// some expressions can be evaluated as a constant if they refer to
+ /// variables in some cases. See PR26210 for the discussion.
+ bool IsMicrosoftABI;
+
+ /// \brief True if we are looking for a DeclRefExpr.
+ bool LookingForDeclRefExpr;
+
+ /// \brief True if we have observed a DeclRefExpr since the last time that
+ /// awaitDeclRefExpr() was called. This is used in order to handle Microsoft
+ /// ABI requirements.
+ bool HaveSeenDeclRefExpr;
+
enum EvaluationMode {
/// Evaluate as a constant expression. Stop if we find that the expression
/// is not a constant expression.
@@ -541,7 +554,9 @@
BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
EvaluatingDecl((const ValueDecl *)nullptr),
EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
- HasFoldFailureDiagnostic(false), EvalMode(Mode) {}
+ HasFoldFailureDiagnostic(false), IsMicrosoftABI(false),
+ LookingForDeclRefExpr(false), HaveSeenDeclRefExpr(false),
+ EvalMode(Mode) {}
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base;
@@ -766,6 +781,22 @@
bool allowInvalidBaseExpr() const {
return EvalMode == EM_DesignatorFold;
}
+
+ /// Use the Microsoft ABI during evaluation.
+ void useMicrosoftABI() {
+ IsMicrosoftABI = true;
+ }
+
+ /// Start watching for a DeclRefExpr.
+ void awaitDeclRefExpr() {
+ LookingForDeclRefExpr = true;
+ HaveSeenDeclRefExpr = false;
+ }
+
+ /// Remember that we have observed a DeclRefExpr.
+ void noteDeclRefExpr() {
+ HaveSeenDeclRefExpr = true;
+ }
};
/// Object used to treat all foldable expressions as constant expressions.
@@ -814,13 +845,14 @@
/// RAII object used to suppress diagnostics and side-effects from a
/// speculative evaluation.
class SpeculativeEvaluationRAII {
- EvalInfo &Info;
Expr::EvalStatus Old;
+ protected:
+ EvalInfo &Info;
public:
SpeculativeEvaluationRAII(EvalInfo &Info,
SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr)
- : Info(Info), Old(Info.EvalStatus) {
+ : Old(Info.EvalStatus), Info(Info) {
Info.EvalStatus.Diag = NewDiag;
// If we're speculatively evaluating, we may have skipped over some
// evaluations and missed out a side effect.
@@ -831,6 +863,18 @@
}
};
+ class SpeculativeLookForDeclRefExprRAII final : SpeculativeEvaluationRAII {
+ public:
+ SpeculativeLookForDeclRefExprRAII(EvalInfo &Info,
+ SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr)
+ : SpeculativeEvaluationRAII(Info, NewDiag) {
+ Info.awaitDeclRefExpr();
+ }
+ ~SpeculativeLookForDeclRefExprRAII() {
+ Info.LookingForDeclRefExpr = false;
+ }
+ };
+
/// RAII object wrapping a full-expression or block scope, and handling
/// the ending of the lifetime of temporaries created within it.
template<bool IsFullExpression>
@@ -4039,6 +4083,18 @@
Error(E, diag::note_constexpr_conditional_never_const);
}
+ // Check whether an expression contains a DeclRefExpr where not permitted by
+ // the Microsoft ABI.
+ template<typename Expr>
+ bool CheckPotentialExpressionContainingDeclRefExpr(const Expr *E) {
+ SmallVector<PartialDiagnosticAt, 8> Diag;
+ SpeculativeLookForDeclRefExprRAII Speculate(Info, &Diag);
+
+ StmtVisitorTy::Visit(E);
+ if (Info.HaveSeenDeclRefExpr)
+ return Error(E, diag::note_constexpr_microsoft_abi_declrefexpr);
+ return true;
+ }
template<typename ConditionalOperator>
bool HandleConditionalOperator(const ConditionalOperator *E) {
@@ -4050,6 +4106,13 @@
}
Expr *EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
+ if (Info.IsMicrosoftABI) {
+ // In the Microsoft ABI, a DeclRefExpr on either side of the conditional
+ // operator will prevent us from evaluating the expression to a constant.
+ if (!CheckPotentialExpressionContainingDeclRefExpr(E->getTrueExpr(),
+ E->getFalseExpr()))
+ return false;
+ }
return StmtVisitorTy::Visit(EvalExpr);
}
@@ -4064,6 +4127,15 @@
bool ZeroInitialization(const Expr *E) { return Error(E); }
+ // Check whether either of the two expressions contains a DeclRefExpr where
+ // not permitted by the Microsoft ABI.
+ template<typename ExprLHS, typename ExprRHS>
+ bool CheckPotentialExpressionContainingDeclRefExpr(const ExprLHS *ELHS,
+ const ExprRHS *ERHS) {
+ return CheckPotentialExpressionContainingDeclRefExpr(ELHS) &&
+ CheckPotentialExpressionContainingDeclRefExpr(ERHS);
+ }
+
public:
ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
@@ -4626,6 +4698,8 @@
}
bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
+ Info.noteDeclRefExpr();
+
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl()))
return Success(FD);
if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
@@ -6069,6 +6143,8 @@
bool CheckReferencedDecl(const Expr *E, const Decl *D);
bool VisitDeclRefExpr(const DeclRefExpr *E) {
+ Info.noteDeclRefExpr();
+
if (CheckReferencedDecl(E, E->getDecl()))
return true;
@@ -7186,6 +7262,20 @@
}
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ if (Info.IsMicrosoftABI) {
+ switch (E->getOpcode()) {
+ case BO_Comma:
+ case BO_LAnd:
+ case BO_LOr:
+ // In the Microsoft ABI, a DeclRefExpr on either side of some binary
+ // operators will prevent us from evaluating the expression to a constant.
+ if (!CheckPotentialExpressionContainingDeclRefExpr(E->getLHS(), E->getRHS()))
+ return false;
+ default:
+ /* No need to do anything. */ ;
+ }
+ }
+
if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp())
return Error(E);
@@ -8915,6 +9005,9 @@
: EvalInfo::EM_ConstantFold);
InitInfo.setEvaluatingDecl(VD, Value);
+ if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
+ InitInfo.useMicrosoftABI();
+
LValue LVal;
LVal.set(VD);
Index: include/clang/Basic/DiagnosticASTKinds.td
===================================================================
--- include/clang/Basic/DiagnosticASTKinds.td
+++ include/clang/Basic/DiagnosticASTKinds.td
@@ -148,6 +148,9 @@
def note_constexpr_baa_value_insufficient_alignment : Note<
"value of the aligned pointer (%0) is not a multiple of the asserted %1 "
"%plural{1:byte|:bytes}1">;
+def note_constexpr_microsoft_abi_declrefexpr : Note<
+ "the constant expression cannot contain a reference to a variable as a Microsoft "
+ "ABI extension">;
def warn_integer_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
Index: examples/PrintFunctionNames/PrintFunctionNames.cpp
===================================================================
--- examples/PrintFunctionNames/PrintFunctionNames.cpp
+++ examples/PrintFunctionNames/PrintFunctionNames.cpp
@@ -121,3 +121,4 @@
static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
X("print-fns", "print function names");
+LLVM_EXPORT_REGISTRY(FrontendPluginRegistry)
Index: docs/ClangPlugins.rst
===================================================================
--- docs/ClangPlugins.rst
+++ docs/ClangPlugins.rst
@@ -37,11 +37,14 @@
====================
A plugin is loaded from a dynamic library at runtime by the compiler. To
-register a plugin in a library, use ``FrontendPluginRegistry::Add<>``:
+register a plugin in a library, use ``FrontendPluginRegistry::Add<>``.
+On Windows, you also need to export your plugin registry using
+``LLVM_EXPORT_REGISTRY``. Here is an example:
.. code-block:: c++
static FrontendPluginRegistry::Add<MyPlugin> X("my-plugin-name", "my plugin description");
+ LLVM_EXPORT_REGISTRY(FrontendPluginRegistry)
Putting it all together
=======================
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits