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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to