diff --git a/Test/baseResults/hlsl.attribute.frag.out b/Test/baseResults/hlsl.attribute.frag.out
new file mode 100755
index 0000000000000000000000000000000000000000..6ee4a24659c35415d4721032c0c6516dd4fd1a39
--- /dev/null
+++ b/Test/baseResults/hlsl.attribute.frag.out
@@ -0,0 +1,57 @@
+hlsl.attribute.frag
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:14  Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float)
+0:2    Function Parameters: 
+0:2      'input' (temp 4-component vector of float)
+0:?     Sequence
+0:11      Test condition and select (temp void)
+0:11        Condition
+0:11        Constant:
+0:11          0 (const int)
+0:11        true case is null
+0:?   Linker Objects
+
+
+Linked fragment stage:
+
+
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:14  Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float)
+0:2    Function Parameters: 
+0:2      'input' (temp 4-component vector of float)
+0:?     Sequence
+0:11      Test condition and select (temp void)
+0:11        Condition
+0:11        Constant:
+0:11          0 (const int)
+0:11        true case is null
+0:?   Linker Objects
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 10
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "PixelShaderFunction"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 450
+                              Name 4  "PixelShaderFunction"
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:      6(int) Constant 0
+4(PixelShaderFunction):           2 Function None 3
+               5:             Label
+                              SelectionMerge 9 None
+                              BranchConditional 7 8 9
+               8:               Label
+                                Branch 9
+               9:             Label
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/hlsl.if.frag.out b/Test/baseResults/hlsl.if.frag.out
new file mode 100755
index 0000000000000000000000000000000000000000..8908279bac7c7971254f8122afa1944f02e8fe0a
--- /dev/null
+++ b/Test/baseResults/hlsl.if.frag.out
@@ -0,0 +1,223 @@
+hlsl.if.frag
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:29  Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float)
+0:2    Function Parameters: 
+0:2      'input' (temp 4-component vector of float)
+0:?     Sequence
+0:3      Test condition and select (temp void)
+0:3        Condition
+0:3        Compare Equal (temp bool)
+0:3          'input' (temp 4-component vector of float)
+0:3          'input' (temp 4-component vector of float)
+0:3        true case
+0:4        Branch: Return with expression
+0:4          'input' (temp 4-component vector of float)
+0:6      Test condition and select (temp void)
+0:6        Condition
+0:6        Compare Equal (temp bool)
+0:6          'input' (temp 4-component vector of float)
+0:6          'input' (temp 4-component vector of float)
+0:6        true case
+0:7        Branch: Return with expression
+0:7          'input' (temp 4-component vector of float)
+0:6        false case
+0:9        Branch: Return with expression
+0:9          Negate value (temp 4-component vector of float)
+0:9            'input' (temp 4-component vector of float)
+0:11      Test condition and select (temp void)
+0:11        Condition
+0:11        Compare Equal (temp bool)
+0:11          'input' (temp 4-component vector of float)
+0:11          'input' (temp 4-component vector of float)
+0:11        true case is null
+0:14      Test condition and select (temp void)
+0:14        Condition
+0:14        Compare Equal (temp bool)
+0:14          'input' (temp 4-component vector of float)
+0:14          'input' (temp 4-component vector of float)
+0:14        true case is null
+0:19      Test condition and select (temp void)
+0:19        Condition
+0:19        Compare Equal (temp bool)
+0:19          'input' (temp 4-component vector of float)
+0:19          'input' (temp 4-component vector of float)
+0:19        true case
+0:?         Sequence
+0:20          Branch: Return with expression
+0:20            'input' (temp 4-component vector of float)
+0:23      Test condition and select (temp void)
+0:23        Condition
+0:23        Compare Equal (temp bool)
+0:23          'input' (temp 4-component vector of float)
+0:23          'input' (temp 4-component vector of float)
+0:23        true case
+0:?         Sequence
+0:24          Branch: Return with expression
+0:24            'input' (temp 4-component vector of float)
+0:23        false case
+0:?         Sequence
+0:26          Branch: Return with expression
+0:26            Negate value (temp 4-component vector of float)
+0:26              'input' (temp 4-component vector of float)
+0:?   Linker Objects
+
+
+Linked fragment stage:
+
+
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:29  Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float)
+0:2    Function Parameters: 
+0:2      'input' (temp 4-component vector of float)
+0:?     Sequence
+0:3      Test condition and select (temp void)
+0:3        Condition
+0:3        Compare Equal (temp bool)
+0:3          'input' (temp 4-component vector of float)
+0:3          'input' (temp 4-component vector of float)
+0:3        true case
+0:4        Branch: Return with expression
+0:4          'input' (temp 4-component vector of float)
+0:6      Test condition and select (temp void)
+0:6        Condition
+0:6        Compare Equal (temp bool)
+0:6          'input' (temp 4-component vector of float)
+0:6          'input' (temp 4-component vector of float)
+0:6        true case
+0:7        Branch: Return with expression
+0:7          'input' (temp 4-component vector of float)
+0:6        false case
+0:9        Branch: Return with expression
+0:9          Negate value (temp 4-component vector of float)
+0:9            'input' (temp 4-component vector of float)
+0:11      Test condition and select (temp void)
+0:11        Condition
+0:11        Compare Equal (temp bool)
+0:11          'input' (temp 4-component vector of float)
+0:11          'input' (temp 4-component vector of float)
+0:11        true case is null
+0:14      Test condition and select (temp void)
+0:14        Condition
+0:14        Compare Equal (temp bool)
+0:14          'input' (temp 4-component vector of float)
+0:14          'input' (temp 4-component vector of float)
+0:14        true case is null
+0:19      Test condition and select (temp void)
+0:19        Condition
+0:19        Compare Equal (temp bool)
+0:19          'input' (temp 4-component vector of float)
+0:19          'input' (temp 4-component vector of float)
+0:19        true case
+0:?         Sequence
+0:20          Branch: Return with expression
+0:20            'input' (temp 4-component vector of float)
+0:23      Test condition and select (temp void)
+0:23        Condition
+0:23        Compare Equal (temp bool)
+0:23          'input' (temp 4-component vector of float)
+0:23          'input' (temp 4-component vector of float)
+0:23        true case
+0:?         Sequence
+0:24          Branch: Return with expression
+0:24            'input' (temp 4-component vector of float)
+0:23        false case
+0:?         Sequence
+0:26          Branch: Return with expression
+0:26            Negate value (temp 4-component vector of float)
+0:26              'input' (temp 4-component vector of float)
+0:?   Linker Objects
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 64
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "PixelShaderFunction"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 450
+                              Name 4  "PixelShaderFunction"
+                              Name 9  "input"
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Function 7(fvec4)
+              12:             TypeBool
+              13:             TypeVector 12(bool) 4
+4(PixelShaderFunction):           2 Function None 3
+               5:             Label
+        9(input):      8(ptr) Variable Function
+              10:    7(fvec4) Load 9(input)
+              11:    7(fvec4) Load 9(input)
+              14:   13(bvec4) FOrdEqual 10 11
+              15:    12(bool) All 14
+                              SelectionMerge 17 None
+                              BranchConditional 15 16 17
+              16:               Label
+              18:    7(fvec4)   Load 9(input)
+                                ReturnValue 18
+              17:             Label
+              20:    7(fvec4) Load 9(input)
+              21:    7(fvec4) Load 9(input)
+              22:   13(bvec4) FOrdEqual 20 21
+              23:    12(bool) All 22
+                              SelectionMerge 25 None
+                              BranchConditional 23 24 28
+              24:               Label
+              26:    7(fvec4)   Load 9(input)
+                                ReturnValue 26
+              28:               Label
+              29:    7(fvec4)   Load 9(input)
+              30:    7(fvec4)   FNegate 29
+                                ReturnValue 30
+              25:             Label
+              32:    7(fvec4) Load 9(input)
+              33:    7(fvec4) Load 9(input)
+              34:   13(bvec4) FOrdEqual 32 33
+              35:    12(bool) All 34
+                              SelectionMerge 37 None
+                              BranchConditional 35 36 37
+              36:               Label
+                                Branch 37
+              37:             Label
+              38:    7(fvec4) Load 9(input)
+              39:    7(fvec4) Load 9(input)
+              40:   13(bvec4) FOrdEqual 38 39
+              41:    12(bool) All 40
+                              SelectionMerge 43 None
+                              BranchConditional 41 42 43
+              42:               Label
+                                Branch 43
+              43:             Label
+              44:    7(fvec4) Load 9(input)
+              45:    7(fvec4) Load 9(input)
+              46:   13(bvec4) FOrdEqual 44 45
+              47:    12(bool) All 46
+                              SelectionMerge 49 None
+                              BranchConditional 47 48 49
+              48:               Label
+              50:    7(fvec4)   Load 9(input)
+                                ReturnValue 50
+              49:             Label
+              52:    7(fvec4) Load 9(input)
+              53:    7(fvec4) Load 9(input)
+              54:   13(bvec4) FOrdEqual 52 53
+              55:    12(bool) All 54
+                              SelectionMerge 57 None
+                              BranchConditional 55 56 60
+              56:               Label
+              58:    7(fvec4)   Load 9(input)
+                                ReturnValue 58
+              60:               Label
+              61:    7(fvec4)   Load 9(input)
+              62:    7(fvec4)   FNegate 61
+                                ReturnValue 62
+              57:             Label
+                              Return
+                              FunctionEnd
diff --git a/Test/hlsl.attribute.frag b/Test/hlsl.attribute.frag
new file mode 100644
index 0000000000000000000000000000000000000000..25c72d46efd90cb07c8f639381e8afd2ea1a6da3
--- /dev/null
+++ b/Test/hlsl.attribute.frag
@@ -0,0 +1,13 @@
+float4 PixelShaderFunction(float4 input) : COLOR0
+{
+    [unroll];
+    [];
+    [][][];
+    [unroll(4)];
+    [allow_uav_condition];
+    [unroll(4)] [allow_uav_condition];
+    [  loop  ];
+    [fastopt];
+    [branch] if (0);
+    [flatten];
+}
diff --git a/Test/hlsl.if.frag b/Test/hlsl.if.frag
new file mode 100644
index 0000000000000000000000000000000000000000..1f0dde713e1f362a2b1e7560dc80f9f2eef10675
--- /dev/null
+++ b/Test/hlsl.if.frag
@@ -0,0 +1,28 @@
+float4 PixelShaderFunction(float4 input) : COLOR0
+{
+    if (input == input)
+        return input;
+
+    if (input == input)
+        return input;
+    else
+        return -input;
+
+    if (input == input)
+        ;
+
+    if (input == input)
+        ;
+    else
+        ;
+
+    [flatten] if (input == input) {
+        return input;
+    }
+
+    if (input == input) {
+        return input;
+    } else {
+        return -input;
+    }
+}
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 9c0061ed296e9a25781bb3beb4a62a3a3665ef11..123dd6085d29e911ca5728804b096f6ae9399a57 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -73,9 +73,11 @@ INSTANTIATE_TEST_CASE_P(
     ToSpirv, HlslCompileTest,
     ::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
         {"hlsl.assoc.frag", "PixelShaderFunction"},
+        {"hlsl.attribute.frag", "PixelShaderFunction"},
         {"hlsl.cast.frag", "PixelShaderFunction"},
         {"hlsl.float1.frag", "PixelShaderFunction"},
         {"hlsl.float4.frag", "PixelShaderFunction"},
+        {"hlsl.if.frag", "PixelShaderFunction"},
         {"hlsl.intrinsics.frag", "PixelShaderFunction"},
         {"hlsl.intrinsics.negative.frag", "PixelShaderFunction"},
         {"hlsl.intrinsics.negative.vert", "VertexShaderFunction"},
diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp
index 31e67d3607713aa2ab785ba93891697a31ba004f..a75fee6dcff6524b018d4d9ac00677350bf645b4 100755
--- a/hlsl/hlslGrammar.cpp
+++ b/hlsl/hlslGrammar.cpp
@@ -434,7 +434,7 @@ bool HlslGrammar::acceptFunctionParameters(TFunction& function)
 
     // RIGHT_PAREN
     if (! acceptTokenClass(EHTokRightParen)) {
-        expected("right parenthesis");
+        expected(")");
         return false;
     }
 
@@ -485,6 +485,31 @@ bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& no
     return false;
 }
 
+// Accept an expression with parenthesis around it, where
+// the parenthesis ARE NOT expression parenthesis, but the
+// syntactically required ones like in "if ( expression )"
+//
+// Note this one is not set up to be speculative; as it gives
+// errors if not found.
+//
+bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
+{
+    // LEFT_PAREN
+    if (! acceptTokenClass(EHTokLeftParen))
+        expected("(");
+
+    if (! acceptExpression(expression)) {
+        expected("expression");
+        return false;
+    }
+
+    // RIGHT_PAREN
+    if (! acceptTokenClass(EHTokRightParen))
+        expected(")");
+
+    return true;
+}
+
 // The top-level full expression recognizer.
 //
 // expression
@@ -620,7 +645,7 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
         TType castType;
         if (acceptType(castType)) {
             if (! acceptTokenClass(EHTokRightParen)) {
-                expected("right parenthesis");
+                expected(")");
                 return false;
             }
 
@@ -699,7 +724,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
             return false;
         }
         if (! acceptTokenClass(EHTokRightParen)) {
-            expected("right parenthesis");
+            expected(")");
             return false;
         }
     } else if (acceptLiteral(node)) {
@@ -838,7 +863,7 @@ bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
 
     // RIGHT_PAREN
     if (! acceptTokenClass(EHTokRightParen)) {
-        expected("right parenthesis");
+        expected(")");
         return false;
     }
 
@@ -896,6 +921,24 @@ bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
     return acceptTokenClass(EHTokRightBrace);
 }
 
+bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
+{
+    parseContext.pushScope();
+    bool result = acceptNestedStatement(statement);
+    parseContext.popScope();
+
+    return result;
+}
+
+bool HlslGrammar::acceptNestedStatement(TIntermNode*& statement)
+{
+    parseContext.nestStatement();
+    bool result = acceptStatement(statement);
+    parseContext.unnestStatement();
+
+    return result;
+}
+
 // statement
 //      : attributes attributed_statement
 //
@@ -965,7 +1008,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
 
             // SEMICOLON (following an expression)
             if (! acceptTokenClass(EHTokSemicolon)) {
-                expected("semicolon");
+                expected(";");
                 return false;
             }
         }
@@ -989,12 +1032,86 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
 //
 void HlslGrammar::acceptAttributes()
 {
-    // TODO
+    // For now, accept the [ XXX(X) ] syntax, but drop.
+    // TODO: subset to correct set?  Pass on?
+    do {
+        // LEFT_BRACKET?
+        if (! acceptTokenClass(EHTokLeftBracket))
+            return;
+
+        // attribute
+        if (peekTokenClass(EHTokIdentifier)) {
+            // 'token.string' is the attribute
+            advanceToken();
+        } else if (! peekTokenClass(EHTokRightBracket)) {
+            expected("identifier");
+            advanceToken();
+        }
+
+        // (x)
+        if (acceptTokenClass(EHTokLeftParen)) {
+            TIntermTyped* node;
+            if (! acceptLiteral(node))
+                expected("literal");
+            // 'node' has the literal in it
+            if (! acceptTokenClass(EHTokRightParen))
+                expected(")");
+        }
+
+        // RIGHT_BRACKET
+        if (acceptTokenClass(EHTokRightBracket))
+            continue;
+
+        expected("]");
+        return;
+
+    } while (true);
 }
 
+// selection_statement
+//      : IF LEFT_PAREN expression RIGHT_PAREN statement
+//      : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
+//
 bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
 {
-    return false;
+    TSourceLoc loc = token.loc;
+
+    // IF
+    if (! acceptTokenClass(EHTokIf))
+        return false;
+
+    // so that something declared in the condition is scoped to the lifetimes
+    // of the then-else statements
+    parseContext.pushScope();
+
+    // LEFT_PAREN expression RIGHT_PAREN
+    TIntermTyped* condition;
+    if (! acceptParenExpression(condition))
+        return false;
+
+    // create the child statements
+    TIntermNodePair thenElse = { nullptr, nullptr };
+
+    // then statement
+    if (! acceptScopedStatement(thenElse.node1)) {
+        expected("then statement");
+        return false;
+    }
+
+    // ELSE
+    if (acceptTokenClass(EHTokElse)) {
+        // else statement
+        if (! acceptScopedStatement(thenElse.node2)) {
+            expected("else statement");
+            return false;
+        }
+    }
+
+    // Put the pieces together
+    statement = intermediate.addSelection(condition, thenElse, loc);
+    parseContext.popScope();
+
+    return true;
 }
 
 bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
@@ -1036,7 +1153,7 @@ bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
 
             // SEMICOLON
             if (! acceptTokenClass(EHTokSemicolon)) {
-                expected("semicolon");
+                expected(";");
                 return false;
             }
 
diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h
index 7d337fde9d2f0df2d5921d726e1b25f1fa4b0c84..69535f30b9fcae4865eed06713fd6a4467451fdb 100755
--- a/hlsl/hlslGrammar.h
+++ b/hlsl/hlslGrammar.h
@@ -64,6 +64,7 @@ namespace glslang {
         bool acceptFunctionParameters(TFunction&);
         bool acceptParameterDeclaration(TFunction&);
         bool acceptFunctionDefinition(TFunction&, TIntermNode*&);
+        bool acceptParenExpression(TIntermTyped*&);
         bool acceptExpression(TIntermTyped*&);
         bool acceptAssignmentExpression(TIntermTyped*&);
         bool acceptBinaryExpression(TIntermTyped*&, PrecedenceLevel);
@@ -75,6 +76,8 @@ namespace glslang {
         bool acceptLiteral(TIntermTyped*&);
         bool acceptCompoundStatement(TIntermNode*&);
         bool acceptStatement(TIntermNode*&);
+        bool acceptScopedStatement(TIntermNode*&);
+        bool acceptNestedStatement(TIntermNode*&);
         void acceptAttributes();
         bool acceptSelectionStatement(TIntermNode*&);
         bool acceptSwitchStatement(TIntermNode*&);
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index 7fa267ff91d7f2314941662992c2f454617789fd..a6c59a32ae22a84eb0efb23860da4e83bb2025f5 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -139,6 +139,11 @@ public:
 
     void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
 
+    void nestStatement()   { ++statementNestingLevel; }
+    void unnestStatement() { --statementNestingLevel; }
+    void pushScope()       { symbolTable.push(); }
+    void popScope()        { symbolTable.pop(0); }
+
 protected:
     void inheritGlobalDefaults(TQualifier& dst) const;
     TVariable* makeInternalVariable(const char* name, const TType&) const;