Index: test/Sema/noop.cc
===================================================================
--- test/Sema/noop.cc	(revision 0)
+++ test/Sema/noop.cc	(revision 0)
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -fms-extensions %s
+
+template<typename T> static void f() { T x = 10; }
+void g() { __noop(f<void>()); }
+
+void err0() {  __noop int; }  // expected-error {{expected '(' after '__noop'}}
+void err1() {  __noop(int); }  // expected-error {{expected '(' for function-style cast or type construction}}
+void err2() {  __noop 4; }  // expected-error {{expected '(' after '__noop'}}
+void err3() {  int a = 4; __noop(a)++; }  // expected-error {{expected ';' after expression}} expected-error {{expected expression}}
+void err4() {  int a = 4; __noop(float)a; }  // expected-error {{expected '(' for function-style cast or type construction}}
+void err5() { __noop[]; }  // expected-error {{expected '(' after '__noop'}}
+
+void err6() { __noop({}); }  // expected-error {{expected expression}}
+
+void j() {
+  int a = __noop(4);  // Inits to 0.
+  __noop(a);
+
+  __noop(4);  // shouldn't warn about an unused result
+
+  __noop(1, 2, 3, 4, 5);
+  __noop();
+
+  __noop((float)a);
+}
+
+struct S {};
+class C {  // expected-note 2 {{no known conversion}}
+ public:
+  C(S) {}  // expected-note 2 {{no known conversion}}
+};
+
+void k() {
+  S s;
+  C c1(__noop(s));  // expected-error {{no matching constructor for initialization of 'C'}}
+  C c2 = __noop(s);  // expected-error {{no viable conversion from 'unsigned long' to 'C'}}
+
+  int arr[__noop()];  // XXX check if cl permits this
+}
+
+// XXX test signedness
Index: include/clang/Basic/TypeTraits.h
===================================================================
--- include/clang/Basic/TypeTraits.h	(revision 164668)
+++ include/clang/Basic/TypeTraits.h	(working copy)
@@ -84,7 +84,8 @@
   enum UnaryExprOrTypeTrait {
     UETT_SizeOf,
     UETT_AlignOf,
-    UETT_VecStep
+    UETT_VecStep,
+    UETT_Noop
   };
   
   /// \brief Names for type traits that operate specifically on types.
Index: include/clang/Basic/Builtins.def
===================================================================
--- include/clang/Basic/Builtins.def	(revision 164668)
+++ include/clang/Basic/Builtins.def	(working copy)
@@ -663,7 +663,6 @@
 
 // Microsoft builtins.
 BUILTIN(__assume, "vb", "n")
-BUILTIN(__noop, "v.", "n")
 BUILTIN(__debugbreak, "v", "n")
 
 
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def	(revision 164668)
+++ include/clang/Basic/TokenKinds.def	(working copy)
@@ -501,6 +501,7 @@
 KEYWORD(__try                         , KEYMS | KEYBORLAND)
 KEYWORD(__finally                     , KEYMS | KEYBORLAND)
 KEYWORD(__leave                       , KEYMS | KEYBORLAND)
+KEYWORD(__noop                        , KEYMS)
 KEYWORD(__int64                       , KEYMS)
 KEYWORD(__if_exists                   , KEYMS)
 KEYWORD(__if_not_exists               , KEYMS)
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp	(revision 164668)
+++ lib/Sema/SemaExpr.cpp	(working copy)
@@ -2960,6 +2960,9 @@
 /// instantiation, etc.
 bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
                                             UnaryExprOrTypeTrait ExprKind) {
+  if (ExprKind == UETT_Noop)
+    return false;
+
   QualType ExprTy = E->getType();
 
   // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
@@ -3028,7 +3031,7 @@
                                             SourceLocation OpLoc,
                                             SourceRange ExprRange,
                                             UnaryExprOrTypeTrait ExprKind) {
-  if (ExprType->isDependentType())
+  if (ExprType->isDependentType() || ExprKind == UETT_Noop)
     return false;
 
   // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
@@ -3100,6 +3103,7 @@
                                      SourceLocation OpLoc,
                                      UnaryExprOrTypeTrait ExprKind,
                                      SourceRange R) {
+  assert(ExprKind != UETT_Noop && "__noop cannot take a type parameter");
   if (!TInfo)
     return ExprError();
 
@@ -3134,6 +3138,8 @@
     isInvalid = CheckAlignOfExpr(*this, E);
   } else if (ExprKind == UETT_VecStep) {
     isInvalid = CheckVecStepExpr(E);
+  } else if (ExprKind == UETT_Noop) {
+    isInvalid = false;
   } else if (E->getBitField()) {  // C99 6.5.3.4p1.
     Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
     isInvalid = true;
Index: lib/AST/StmtDumper.cpp
===================================================================
--- lib/AST/StmtDumper.cpp	(revision 164668)
+++ lib/AST/StmtDumper.cpp	(working copy)
@@ -469,6 +469,9 @@
   case UETT_VecStep:
     OS << " vec_step ";
     break;
+  case UETT_Noop:
+    OS << " __noop ";
+    break;
   }
   if (Node->isArgumentType())
     DumpType(Node->getArgumentType());
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp	(revision 164668)
+++ lib/AST/ExprConstant.cpp	(working copy)
@@ -5168,10 +5168,10 @@
 }
 
 
-/// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with
-/// a result as the expression's type.
+/// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof, vec_step, or
+/// noop with a result as the expression's type.
 bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
-                                    const UnaryExprOrTypeTraitExpr *E) {
+    const UnaryExprOrTypeTraitExpr *E) {
   switch(E->getKind()) {
   case UETT_AlignOf: {
     if (E->isArgumentType())
@@ -5208,7 +5208,12 @@
       return false;
     return Success(Sizeof, E);
   }
+
+  case UETT_Noop: {
+    // XXX or return false?
+    return Success(0, E);
   }
+  }
 
   llvm_unreachable("unknown expr/type trait");
 }
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp	(revision 164668)
+++ lib/AST/ItaniumMangle.cpp	(working copy)
@@ -2622,13 +2622,21 @@
     case UETT_AlignOf:
       Out << 'a';
       break;
-    case UETT_VecStep:
+    case UETT_VecStep: {
       DiagnosticsEngine &Diags = Context.getDiags();
       unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
                                      "cannot yet mangle vec_step expression");
       Diags.Report(DiagID);
       return;
     }
+    case UETT_Noop: {
+      DiagnosticsEngine &Diags = Context.getDiags();
+      unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+                                     "cannot mangle __noop expressions");
+      Diags.Report(DiagID);
+      return;
+    }
+    }
     if (SAE->isArgumentType()) {
       Out << 't';
       mangleType(SAE->getArgumentType());
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp	(revision 164668)
+++ lib/AST/StmtPrinter.cpp	(working copy)
@@ -848,6 +848,9 @@
   case UETT_VecStep:
     OS << "vec_step";
     break;
+  case UETT_Noop:
+    OS << "__noop";
+    break;
   }
   if (Node->isArgumentType())
     OS << "(" << Node->getArgumentType().getAsString(Policy) << ")";
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp	(revision 164668)
+++ lib/AST/Expr.cpp	(working copy)
@@ -1844,6 +1844,21 @@
     R1 = UO->getSubExpr()->getSourceRange();
     return true;
   }
+  case UnaryExprOrTypeTraitExprClass: {
+    const UnaryExprOrTypeTraitExpr *UE = cast<UnaryExprOrTypeTraitExpr>(this);
+    switch (UE->getKind()) {
+      case UETT_Noop:
+        return false;
+      case UETT_AlignOf:
+      case UETT_SizeOf:
+      case UETT_VecStep:
+        break;
+    }
+    WarnE = this;
+    Loc = UE->getOperatorLoc();
+    R1 = UE->getSourceRange();
+    return true;
+  }
   case BinaryOperatorClass: {
     const BinaryOperator *BO = cast<BinaryOperator>(this);
     switch (BO->getOpcode()) {
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp	(revision 164668)
+++ lib/Parse/ParseExpr.cpp	(working copy)
@@ -1001,6 +1001,7 @@
   case tok::kw_sizeof:     // unary-expression: 'sizeof' unary-expression
                            // unary-expression: 'sizeof' '(' type-name ')'
   case tok::kw_vec_step:   // unary-expression: OpenCL 'vec_step' expression
+  case tok::kw___noop:      // unary-expression: MS '__noop' expression
     return ParseUnaryExprOrTypeTraitExpression();
   case tok::ampamp: {      // unary-expression: '&&' identifier
     SourceLocation AmpAmpLoc = ConsumeToken();
@@ -1578,7 +1579,7 @@
 }
 
 /// ParseExprAfterUnaryExprOrTypeTrait - We parsed a typeof/sizeof/alignof/
-/// vec_step and we are at the start of an expression or a parenthesized
+/// vec_step/noop and we are at the start of an expression or a parenthesized
 /// type-id. OpTok is the operand token (typeof/sizeof/alignof). Returns the
 /// expression (isCastExpr == false) or the type (isCastExpr == true).
 ///
@@ -1590,6 +1591,7 @@
 /// [GNU]   '__alignof' '(' type-name ')'
 /// [C11]   '_Alignof' '(' type-name ')'
 /// [C++0x] 'alignof' '(' type-id ')'
+/// [MS]    '__noop' parameter-list
 ///
 /// [GNU]   typeof-specifier:
 ///           typeof ( expressions )
@@ -1608,20 +1610,41 @@
 
   assert((OpTok.is(tok::kw_typeof)    || OpTok.is(tok::kw_sizeof) ||
           OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) ||
-          OpTok.is(tok::kw__Alignof)  || OpTok.is(tok::kw_vec_step)) &&
+          OpTok.is(tok::kw__Alignof)  || OpTok.is(tok::kw_vec_step) ||
+          OpTok.is(tok::kw___noop)) &&
           "Not a typeof/sizeof/alignof/vec_step expression!");
 
   ExprResult Operand;
 
   // If the operand doesn't start with an '(', it must be an expression.
   if (Tok.isNot(tok::l_paren)) {
-    isCastExpr = false;
     if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) {
       Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
       return ExprError();
     }
 
+    if (OpTok.is(tok::kw___noop)) {
+      Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
+      return ExprError();
+    }
+
     Operand = ParseCastExpression(true/*isUnaryExpression*/);
+  } else if (OpTok.is(tok::kw___noop)) {
+    SourceLocation LParenLoc, RParenLoc;
+    if (NextToken().is(tok::r_paren)) {
+      // For __alignof() without any arguments, create a dummy child node.
+      LParenLoc = Tok.getLocation();
+      ConsumeParen();
+      Operand = Actions.ActOnIntegerConstant(Tok.getLocation(), 0);
+      RParenLoc = Tok.getLocation();
+      ConsumeParen();
+    } else {
+      ParenParseOption ExprType = SimpleExpr;
+      LParenLoc = Tok.getLocation();
+      Operand = ParseParenExpression(ExprType, /*stopIfCastExpr=*/false, 
+                                     /*isTypeCast=*/false, CastTy, RParenLoc);
+    }
+    CastRange = SourceRange(LParenLoc, RParenLoc);
   } else {
     // If it starts with a '(', we know that it is either a parenthesized
     // type-name, or it is a unary-expression that starts with a compound
@@ -1672,7 +1695,7 @@
 ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
   assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) ||
           Tok.is(tok::kw_alignof) || Tok.is(tok::kw__Alignof) ||
-          Tok.is(tok::kw_vec_step)) &&
+          Tok.is(tok::kw_vec_step) || Tok.is(tok::kw___noop)) &&
          "Not a sizeof/alignof/vec_step expression!");
   Token OpTok = Tok;
   ConsumeToken();
@@ -1740,6 +1763,8 @@
     ExprKind = UETT_AlignOf;
   else if (OpTok.is(tok::kw_vec_step))
     ExprKind = UETT_VecStep;
+  else if (OpTok.is(tok::kw___noop))
+    ExprKind = UETT_Noop;
 
   if (isCastExpr)
     return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
